2010-02-26 66 views
34

我不明白爲什麼這段代碼不起作用。安全刪除DataRow在ForEach

foreach (DataRow dataRow in dataTable.Rows) 
{ 
    if (true) 
    { 
     dataRow.Delete(); 
    } 
} 
+0

似乎爲我工作。我猜dataTable.Rows.Remove(dataRow);雖然不起作用。 – synergetic 2014-05-02 07:25:48

回答

31

.NET中的大多數集合都不允許您在迭代集合時更改集合的內容。從docs for IEnumerator

一個枚舉仍然有效的,只要 集合保持不變。如果 變化對集合進行,如添加,修改或刪除 元件例如 ,枚舉是 失效且不可恢復和下一 呼叫對MoveNext或重置引發 InvalidOperationException異常。如果 集合在 MoveNext和Current之間修改,則當前返回 它設置的元素,即使枚舉器已經失效 。

最好的解決辦法通常是創建要刪除的項目的一個單獨的集合(例如List<DataRow>),然後將其刪除後,你已經完成迭代。

1

Rows內容的變化,如果你刪除一個行,這使得迭代無效,而你是迭代。

但是,您可以先將行復制到集合中,然後迭代集合並刪除行。這可以確保迭代不會因更改要迭代的數據而中斷。

+0

我該如何做到這一點? – 2010-02-26 12:56:18

0

這適用於幾乎任何收藏。如果您在循環收集時嘗試刪除某個項目,則會遇到問題。例如,如果刪除第3行,則前一行#4變爲第3行。

18

您在使用foreach語句迭代時無法修改集合。

你可以嘗試這樣的事情:

List<DataRow> deletedRows = new List<DataRow>(); 

foreach (DataRow dataRow in dataTable.Rows) 
{ 
    if(true) deletedRows.Add(dataRow); 
} 

foreach(DataRow dataRow in deletedRows) 
{ 
    dataRow.Delete(); 
} 
+6

不正確。用「foreach」迭代時不能修改集合您可以使用標準的for循環。例如:'for(int i = datatable.Rows.length - 1; i> = 0; i - ){//移除行}' – AllenG 2010-04-19 16:20:11

+0

@AllenG:謝謝,我添加了信息。 – 2010-04-19 17:34:28

+0

迭代時刪除是可能的http://stackoverflow.com/questions/3150216/data-table-delete-a-row-in-c-using-loop – Developer 2010-06-30 14:49:58

0

使用此:

for (int i = 0; i < myDataTable.Rows.Count; i++) 

{ 

myDataTable[i].Delete(); 

} 
+3

你實際上想以另一種方式來做到這一點''(int i - mydatatable.rows.count -1; i> = 0; i - )'你的方式可能會導致行被跳過(並且根據我的經驗,通常會 – AllenG 2010-04-19 16:21:12

40

最保險的辦法 - 使用for

for (int i = datatable.Rows.Count - 1; i >= 0; i--) 
{ 
    if (true) 
    { 
     datatable.Rows[i].Delete(); 
    } 
} 

不要忘記AcceptChanges刪除所有標記行:

datatable.AcceptChanges(); 
+3

+1好於創建另一個副本並進行更改 – 2012-07-16 21:01:34

+1

不錯,使用'datatable.AcceptChanges()'真正刪除行,否則它們仍然在數據表中 - RowState爲'deleted' – peter 2015-05-06 11:36:54

+0

已更新答案 – VMAtm 2015-05-06 12:15:40

0

如果項目有Count,這是我做了什麼:

int Count = myTable.Rows.Count; 

while (Count > 0) // replace condition with myTable.Rows.Count if unconditionally performed on all rows 
{ 
    DataRow row = myTable.Rows[0] // or however you want to find your index 

    // do some work 
    myTable.Rows.Remove(row); 

    // if you want to perform a check to break out of while 
    if (someCondition) 
     Count = 0; 
    else 
     Count = myTable.Rows.Count; 
} 

注意,這其中的對象有.GetXXXX()集合,像FileInfo(IIRC),在foreach 刪除項目內容是可以接受的。我考慮的一種解決方案是創建一個擴展方法,該方法提供了一個.GetItems()方法。

4

可能是我的答案不再有用。在使用的foreach的DataRow 異常拋出只出現在NET 2.0和更早的版本,原因是在描述MSDN http://msdn.microsoft.com/en-us/library/system.data.datarow.delete(v=vs.80).aspx

如果行的RowState的添加,該行從表中刪除。

使用Delete方法後,RowState變爲Deleted。在您致電AcceptChanges之前它一直保持已刪除狀態。

刪除的行可以通過調用RejectChanges來取消刪除。

使用的foreach

2
foreach (DataRow dataRow in dataTable.Rows) 
{ 
    if (true) 
    { 
     dataRow.Delete(); 
    } 
} 

dataTable.AcceptChanges(); 

請參考捕捉到understatnd它的工作之前,通過這個問題,你可以調用DataTable.AcceptChanges()。

  1. 剛剛刪除但未從DataTable中刪除。

enter image description here

  • 分段的AcceptChanges前點()函數。 enter image description here
  • 執行AcceptChanges()函數後。 enter image description here
  • 我希望現在解決這個問題。

    +2

    我同意你的回答,但是你如何解釋這個:http://msdn.microsoft.com/en-us/library/system.data.datarow.delete.aspx「刪除不應該在一個foreach中調用在迭代thr時循環一個DataRowCollection對象。刪除將修改集合的狀態。「MSDN文檔中的錯誤? – Eternal21 2014-10-12 19:38:54

    1

    通過使用List來映射想要刪除的行然後刪除DataTable迭代之外的行來實現此目的的最簡單方法。

    C#

    List<DataRow> rowsWantToDelete= new List<DataRow>(); 
    
        foreach (DataRow dr in dt.Rows) 
        { 
         if(/*Your condition*/) 
         { 
          rowsWantToDelete.Add(dr); 
         } 
        } 
    
        foreach(DataRow dr in rowsWantToDelete) 
        { 
         dt.Rows.Remove(dr); 
        } 
    

    VB

    Dim rowsWantToDelete As New List(Of DataRow) 
    
    For Each dr As DataRow In dt 
        If 'Your condition' Then 
         rowsWantToDelete .Add(dr) 
        End If 
    Next 
    
    For Each dr As DataRow In rowsWantToDelete 
        dt.Rows.Remove(dr) 
    Next 
    
    0

    有一個其它版本的軟件(我認爲更容易),我只是用:

    int i=0; 
    while (i < myDataTable.Rows.Count) 
    { 
        if (condition) //should it be deleted? 
         myDataTable.Rows.RemoveAt(i); 
        else 
         i++; 
    } 
    

    這更快。

    0

    只適用於像我這樣尋找特定場景的人, 我需要縮短所花的時間,並且一旦從每一行中提取了一些有用的信息,我就會通過將其標記爲已刪除而排除該行。

    希望這可以幫助某人...

    foreach (DataRow dataRow in dataTable.Rows) 
    { 
        if (dataRow.RowState != DataRowState.Deleted) 
        { 
         if (your condition here) 
         { 
          dataRow.Delete(); 
         } 
        } 
    } 
    
    0

    這是因爲它看起來像試圖拆卸你爬樓梯的樓梯。簡單地說,你不能刪除你迭代的項目。

    因此,您應該使用不同的數組迭代並從數據表Rows屬性中刪除它們。

    foreach (DataRow dataRow in dataTable.Select()) 
    { 
        if (true) 
        { 
         dataTable.Rows.Remove(dataRow); 
        } 
    } 
    
    0

    當然Magents

    這是我做到了,工作正常

    dt = GetStationeryConsolidationDetails(txtRefNo.Text); 
    int intRows = dt.Rows.Count; 
    int x = 0; 
    for (int c = 0; c < intRows; c++) 
    { 
        if (dt.Rows[c - x]["DQTY"].ToString() == "0") 
        { 
        dt.Rows[c - x].Delete(); 
        dt.AcceptChanges(); 
        x++;   
        } 
    } 
    
    +0

    **來自複審隊列**:我可以請求您請您在答案中添加更多上下文,僅用於代碼的答案很難理解,它將有助於提問者和未來的讀者,如果你可以在你的文章中添加更多的信息。 – RBT 2017-05-10 09:22:24