2012-10-10 23 views
4

我有兩個表,如DTTable1和DTTable2。它有以下記錄。使用C#比較和刪除數據錶行:

DTTable1:

ItemID  Specification Amount 
    --------- --------------- --------- 
     1    A    10 
     1    B    20 
     1    C    30 

DTTable1:

ItemID  Specification Amount 
    --------- --------------- --------- 
     1    A    10 
     1    B    20 
     1    C    30 
     2    A    10 
     2    B    20 
     3    A    10 
     3    B    20 

在這裏,我想這兩個表進行比較。如果DTTable1記錄存在於DTTable2中(僅考慮ItemID),則刪除ItemID與DTTable1相同的相應行。

我試過foreach和forloop。 及如何使用foreach:

foreach (DataRow DR in DTTable2.Rows) 
    { 
     if (DR["ItemID"].ToString() == DTTable1.Rows[0]["ItemID"].ToString()) 
     { 
      DTTable2.Rows.Remove(DR);        
     } 
    } 
    DTTable2.AcceptChanges(); 

它顯示錯誤, 「集合被修改;枚舉操作可能不會執行」。所以我使用For Loop,它也沒有給出預期的結果。

使用For循環:

for (int i = 0; i < DTTable2.Rows.Count; i++) 
    { 
     if (DTTable2.Rows[i]["ItemID"].ToString() == DTTable1.Rows[0]["ItemID"].ToString()) 
     { 
      DTTable2.Rows.RemoveAt(i); 
     } 
    } 
    DTTable2.AcceptChanges(); 

但有時,第二行不從表中刪除。我得到最終的數據表爲

ItemID  Specification Amount 
    --------- --------------- --------- 
     1    B    20 
     2    A    10 
     2    B    20 
     3    A    10 
     3    B    20 

如何解決這個問題?什麼是最簡單的方法來做到這一點?

+0

你是從數據庫中選擇這些記錄,如果是的話,我可以幫你將只選擇所需的記錄,因爲它查詢更高效地完成sql –

回答

6

不能修改的集合,而你是枚舉它作爲你的第一個例子。您應該獲取要刪除的行的列表,然後將其刪除。

List<DataRow> rowsToDelete = new List<DataRow>(); 
foreach (DataRow DR in DTTable2.Rows) 
{ 
    if (DR["ItemID"].ToString() == DTTable1.Rows[0]["ItemID"].ToString()) 
     rowsToDelete.Add(DR);   
} 

foreach (var r in rowsToDelete) 
    DTTable2.Rows.Remove(r); 

或者,使用內聯LINQ:

DTTable2.Rows 
    .Where(DR => DR["ItemID"].ToString() == DTTable1.Rows[0]["ItemID"].ToString()) 
    .ToList() 
    .ForEach(r => DTTable2.Rows.Remove(r)); 

你的第二個例子失敗,因爲一旦行被刪除,後續行的指標變化,但你繼續遞增i,從而有效地跳過在緊隨刪除行之後的行上。這種情況有解決方法有兩種:

for (int i = DTTable2.Rows.Count - 1; i >= 0; i--) 
    if (DTTable2.Rows[i]["ItemID"].ToString() == DTTable1.Rows[0]["ItemID"].ToString()) 
     DTTable2.Rows.RemoveAt(i); 

或者

int i = 0; 
while (i < DTTable2.Rows.Count) 
{ 
    if (DTTable2.Rows[i]["ItemID"].ToString() == DTTable1.Rows[0]["ItemID"].ToString()) 
     DTTable2.Rows.RemoveAt(i); 
    else 
     i++; 
} 

附註:我想知道你是否真的要始終比較行0的數據,給出你的描述。也許你打算比較下面的所有行(儘管不是最優的)?

if (DTTable1.Any(r => DTTable2.Rows[i]["ItemID"].ToString() == r["ItemID"].ToString())) 
4

嘗試使用:

var list = DTTable2.Rows.ToList();//create new list of rows 
foreach (DataRow DR in list) 
{ 
    //if bla bla bla 
    DTTable2.Rows.Remove(DR); 
} 
+0

非常感謝你... – thevan

4

您可以使用LINQ到數據表

var result = DTTable1.AsEnumerable() 
        .Where(row => !DTTable2.AsEnumerable() 
             .Select(r => r.Field<int>("ItemID")) 
             .Any(x => x == row.Field<int>("ItemID")) 
       ).CopyToDataTable(); 
+0

非常感謝你... – thevan