إزالة DataRow بأمان في Foreach
-
22-09-2019 - |
سؤال
لا أفهم لماذا لا يعمل هذا الرمز.
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
المحلول
بالرغم من DataRow.Delete
لا يعدل حالة المجموعة ، وثائق Microsoft ينص على أنه يجب ألا تسميها أثناء التكرار على المجموعة:
لا يجب استدعاء حذف ولا إزالة في حلقة foreach أثناء التكرار من خلال كائن DataRowCollection. حذف أو إزالة تعديل حالة المجموعة.
أفضل حل هو إنشاء مجموعة منفصلة (على سبيل المثال أ List<DataRow>
) من العناصر التي تريد إزالتها ، ثم إزالتها بعد لقد انتهيت من التكرار.
هذا هو أيضًا الحل للمواقف التي تريد إزالة العناصر من مجموعة ، حيث لا تسمح لك معظم المجموعات في .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();
}
إذا اتصلت بالطريقة الحذف ، فعليك الاتصال فقط AcceptChanges()
على الطاولة تقوم بتعديلها ، بعد حلقة foreach.
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
dataTable.AcceptChanges();
تمثل طريقة الحذف ببساطة الصف للحذف.
http://msdn.microsoft.com/en-us/library/system.data.datarow.delete٪28v=vs.90٪29.aspx
قد تكون إجابتي لم تعد مفيدة. استثناء رمي في Foreach مع DataRow لا يظهر إلا في .NET 2.0 وما قبل ذلك ، والسبب هو الوصف في MSDNhttp://msdn.microsoft.com/en-us/library/system.data.datarow.delete(v=vs.80).aspx
إذا تمت إضافة rowstate من الصف ، تتم إزالة الصف من الجدول.
يتم حذف Rowstate بعد استخدام طريقة Delete. يبقى حذفه حتى تتصل بـ AcceptChanges.
يمكن أن يتم إلغاء الصف المحذوف من خلال استدعاء الرفض.
لتمرير هذه المشكلة ، يمكنك الاتصال بـ datatable.acceptChanges () قبل استخدام Foreach
foreach (DataRow dataRow in dataTable.Rows)
{
if (true)
{
dataRow.Delete();
}
}
dataTable.AcceptChanges();
يرجى إحالة اللقطات إلى عدوى عملها.
- تم حذفها فقط ولكن لم تتم إزالتها من DataTable.
- نقطة الاستراحة قبل قبول accessChanges ().
- بعد eexecuting وظيفة القبول ().
آمل أن يتم حل هذه القضية الآن.
ال Rows
يتغير المحتوى أثناء التكرار إذا قمت بحذف صف واحد ، مما يجعل التكرار غير صالح.
ومع ذلك ، يمكنك نسخ الصفوف إلى مجموعة أولاً ثم تكرارها على المجموعة وحذف الصفوف بهذه الطريقة. هذا يتأكد من أن التكرار لا ينقطع عن طريق تغيير البيانات إلى التكرار.
أسهل طريقة لتحقيق ذلك باستخدام قائمة لتعيين الصفوف التي تريد حذفها ثم حذف الصفوف خارج تكرار البيانات.
ج#
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
هناك نسخة أخرى منه (أعتقد أنه أسهل) ما استخدمته للتو:
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();
}
}
}
هذا ينطبق على أي مجموعة إلى حد كبير. إذا حاولت حذف عنصر أثناء التغلب على المجموعة ، فستواجه مشكلة. على سبيل المثال ، إذا قمت بحذف الصف رقم 3 ، فإن الصف السابق رقم 4 يصبح الصف رقم 3.
حيث تحتوي العناصر على ملف 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()
طريقة.
استخدم هذا:
for (int i = 0; i < myDataTable.Rows.Count; i++)
{
myDataTable[i].Delete();
}
هذا لأنه يبدو أنه يحاول تفكيك درج الدرج الذي تتسلقه. ببساطة ، لا يمكنك إزالة عنصر تكرره.
لذلك يجب عليك استخدام مجموعة مختلفة للتكرار وإزالتها من DataTable Rows
منشأه.
foreach (DataRow dataRow in dataTable.Select())
{
if (true)
{
dataTable.Rows.Remove(dataRow);
}
}
أكد ماجنتس
هكذا فعلت ذلك ويعمل بشكل جيد
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++;
}
}