このコードが機能しない理由がわかりません。
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
たとえ DataRow.Delete
はコレクションの状態を変更しません。 Microsoftのドキュメント は、コレクションを繰り返し処理している間は呼び出してはならないことを示しています。
DataRowCollectionオブジェクトを反復処理している間、foreachループでDeleteもRemoveも呼び出さないでください。削除または削除は、コレクションの状態を変更します。
通常、最善の解決策は、個別のコレクションを作成することです(例:List<DataRow>
)削除したいアイテムを削除し、イテレーションを終了した後after削除します。
これは、コレクションからアイテムを削除する場合のソリューションでもあります。NETのほとんどのコレクションでは、コレクションの繰り返し中にコレクションの内容を変更することはできません。
最も安全な方法-for
ループを使用
for (int i = datatable.Rows.Count - 1; i >= 0; i--)
{
if (true)
{
datatable.Rows[i].Delete();
}
}
AcceptChanges
を忘れずに、すべてのマークされた行を削除します。
datatable.AcceptChanges();
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();
}
Deleteメソッドを呼び出す場合、foreachループの後で、変更するテーブルでAcceptChanges()
を呼び出すだけです。
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
dataTable.AcceptChanges();
Deleteメソッドは、削除する行をマークするだけです。
http://msdn.Microsoft.com/en-us/library/system.data.datarow.delete%28v=VS.90%29.aspx
もはや役に立たない私の答えかもしれません。 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を使用する前にDataTable.AcceptChanges()を呼び出すことができます
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
dataTable.AcceptChanges();
スナップショットを参照して、動作を確認してください。
この問題が解決したことを願っています。
私がちょうど使用したものの他のバージョンがあります(私はもっと簡単だと思います):
int i=0;
while (i < myDataTable.Rows.Count)
{
if (condition) //should it be deleted?
myDataTable.Rows.RemoveAt(i);
else
i++;
}
これは高速です。
私のような特定のシナリオを探している人にのみ、所要時間を短縮する必要があり、いくつかの有用な情報が各行から抽出されたら、削除済みとしてマークして行を除外しました。
これが誰かを助けることを願っています...
foreach (DataRow dataRow in dataTable.Rows)
{
if (dataRow.RowState != DataRowState.Deleted)
{
if (your condition here)
{
dataRow.Delete();
}
}
}
これを実現する最も簡単な方法は、リストを使用して削除する行をマップし、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
1行削除すると、反復中にRows
コンテンツが変更され、反復が無効になります。
ただし、最初に行をコレクションにコピーしてから、コレクションを反復処理し、その方法で行を削除できます。これにより、反復するデータを変更しても反復が中断されないようになります。
これは、登る階段の階段を分解しようとするように見えるためです。単純に、反復するアイテムを削除することはできません。
したがって、異なる配列を使用して、データテーブルのRows
プロパティから反復して削除する必要があります。
foreach (DataRow dataRow in dataTable.Select())
{
if (true)
{
dataTable.Rows.Remove(dataRow);
}
}
アイテムに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;
}
_
オブジェクトがFileInfo
(IIRC)のような.GetXXXX()
コレクションを持っている場合、foreach
内のアイテムのコンテンツを削除することができます。私が検討した解決策の1つは、.GetItems()
メソッドを提供する拡張メソッドを作成することです。
確かな魔術師
これは私がそれをやった方法であり、正常に動作します
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++;
}
}
これを使って:
for (int i = 0; i < myDataTable.Rows.Count; i++)
{
myDataTable[i].Delete();
}
これは、ほとんどすべてのコレクションに適用されます。コレクションをループしているときにアイテムを削除しようとすると、問題が発生します。たとえば、行#3を削除すると、前の行#4は行#3になります。