2013-05-15 120 views
2

我試圖從DataTable AllItems刪除行,從DataTables Items行;這樣做的目的是得到DataTable AllItems項目不屬於內部DataTable Items表沒有主鍵c#

所有這些行從其中包含幾個列和相等同一個Excel文件Fiiled。

我一直在使用foreach循環嘗試:

foreach(DataRow dr in AllItems.Rows) 
{ 
if (Items.Contains(dr)) 
{ 
AllItems.Rows.Remove(dr); 
} 

,但我得到以下錯誤:表沒有主鍵。

有誰知道我可以如何刪除這些行?

+0

這是[最佳](http://msdn.microsoft.com/en-us/library/vstudio/ff926074.aspx)對'variableNames'使用小寫首字母駝峯大小寫。 –

+0

投票結束(發現後添加一個答案):http://stackoverflow.com/questions/4415519/best-way-to-remove-duplicate-entries-from-a-data-table - 特別是,http:///stackoverflow.com/a/15264638/1073107爲刪除重複行提供了非常簡潔的答案。 – dash

回答

1

您有幾種選擇在這裏:

1.添加主鍵

您可以在創建時,它添加一個primary key to your data table

假設你有一個名爲「ID」,那麼你會做這樣的列:

AllItems.PrimaryKey = new DataColumn[] { workTable.Columns["Id"] };} 

或者,因爲你的主鍵是一個複合鍵(多個列)情況:

AllItems.PrimaryKey = new DataColumn[] { 
          workTable.Columns["Id"], 
          workTable.Columns["Name"] };} 

這將允許Contains正常工作。

2.使用數據視圖

您可以使用數據視圖過濾掉重複行;

:使用選擇

或者你可以依靠Select方法來測試,如果基於這就像一個SQL WHEREclause一份聲明中Items DataTable中存在相應的行

DataView view = new DataView(AllItems); 
DataTable distinctValues = view.ToTable(true, "Column1", "Column2" , ..., "ColumnN"); 

3.找到匹配的行

List<DataRow> rowsToRemove = new List<DataRow>(); foreach(DataRow allItemRow in AllItems.Rows) { if(Items.Select(String.Format("Id = {0}"), allItemRow.Field<Int32>("Id")).Length == 0) { rowsToRemove.Add(allItemRow); } } rowsToRemove.ForEach(x => x.Delete()); AllItems.AcceptChanges(); 

注意,它不刪除,而你是在迭代行AllItems的收集行是很重要的 - 相反,收集這些行,並在之後刪除它們。

4.

另外的方式篩選注意,我還沒有嘗試過,但是,這取決於你如何選擇了Excel的行,您可以使用SQL DISTINCT子句;如果您使用的是ODBC to load data from Excel,那麼您可以嘗試在源處進行過濾。

+0

Thx它幫助我:) –

0

你可以試試這個:

var exceptItems = AllItems.Rows.Cast<DataRow>() 
    .Except(Items.Rows.Cast<DataRow>(), DataRowComparer.Default) 
    .ToList(); 

作爲替代方案,如果你想保留從中取出items行後與allItems數據表時,你可以試試這個(假設你有列Id兩個數據表,它唯一地標識每一個數據表中的行)中:

var exceptItems = AllItems.Rows.Cast<DataRow>() 
    .Select((i, index) => new { id = i["Id"], index }) 
    .Intersect(Items.Rows.Cast<DataRow>() 
     .Select((i, index) => new { id = i["Id"], index })) 
    .ToList(); 

for (int i = exceptItems.Count()-1; i >= 0; i--) 
{ 
    AllItems.Rows.RemoveAt(exceptItems[i].index); 
} 

下面是上述最後一個例子中的一個更好的安排:

AllItems.Rows.Cast<DataRow>() 
    .Select((i, index) => new { id = i["Id"], index }) 
    .Intersect(Items.Rows.Cast<DataRow>() 
     .Select((i, index) => new { id = i["Id"], index })) 
    .OrderByDescending(i => i.index) 
    .ToList() 
    .ForEach(i => AllItems.Rows.RemoveAt(i.index)); 
+0

它不會刪除行後,此AllItems.Count是相同的 –

+0

您可以使用'exceptItems'。 –

+0

我添加了兩個從AllItems表中刪除'Items'行的方法。如果你有一個共同的標識行的「Id」列,這些只會起作用。 –