[英]Deleting specific rows from DataTable
我想從數據表中刪除一些行,但它給出了這樣的錯誤,
集合被修改; 枚舉操作可能不會執行
我用於刪除此代碼,
foreach(DataRow dr in dtPerson.Rows){
if(dr["name"].ToString()=="Joe")
dr.Delete();
}
那么,問題是什么以及如何解決? 你建議哪種方法?
如果您從集合中刪除了一個項目,則該集合已被更改並且您無法繼續枚舉它。
相反,使用 For 循環,例如:
for(int i = dtPerson.Rows.Count-1; i >= 0; i--)
{
DataRow dr = dtPerson.Rows[i];
if (dr["name"] == "Joe")
dr.Delete();
}
dtPerson.AcceptChanges();
請注意,您正在反向迭代以避免在刪除當前索引后跳過一行。
在每個人都跳上“您不能刪除枚舉中的行”的潮流之前,您需要首先意識到 DataTables 是事務性的,並且在調用AcceptChanges()之前不要從技術上清除更改
如果您在調用Delete 時看到此異常,則您已經處於待定更改數據狀態。 例如,如果您剛剛從數據庫加載,並且在 foreach 循環中調用 Delete 將引發異常。
但! 但!
如果您從數據庫加載行並調用函數“ AcceptChanges() ”,則您將所有這些掛起的更改提交到 DataTable。 現在您可以遍歷調用 Delete() 的行列表而無需關心,因為它只是將行標記為刪除,但在您再次調用AcceptChanges()之前不會提交
我意識到這個回復有點過時了,但我最近不得不處理一個類似的問題,希望這可以為未來使用 10 年舊代碼的開發人員節省一些痛苦:)
Ps 這是Jeff添加的簡單代碼示例:
C#
YourDataTable.AcceptChanges();
foreach (DataRow row in YourDataTable.Rows) {
// If this row is offensive then
row.Delete();
}
YourDataTable.AcceptChanges();
VB.Net
ds.Tables(0).AcceptChanges()
For Each row In ds.Tables(0).Rows
ds.Tables(0).Rows(counter).Delete()
counter += 1
Next
ds.Tables(0).AcceptChanges()
使用此解決方案:
for(int i = dtPerson.Rows.Count-1; i >= 0; i--)
{
DataRow dr = dtPerson.Rows[i];
if (dr["name"] == "Joe")
dr.Delete();
}
如果要在刪除行后使用數據表,則會出現錯誤。 所以你可以做的是:替換dr.Delete();
與dtPerson.Rows.Remove(dr);
這對我有用,
List<string> lstRemoveColumns = new List<string>() { "ColValue1", "ColVal2", "ColValue3", "ColValue4" };
List<DataRow> rowsToDelete = new List<DataRow>();
foreach (DataRow row in dt.Rows) {
if (lstRemoveColumns.Contains(row["ColumnName"].ToString())) {
rowsToDelete.Add(row);
}
}
foreach (DataRow row in rowsToDelete) {
dt.Rows.Remove(row);
}
dt.AcceptChanges();
DataRow[] dtr=dtPerson.select("name=Joe");
foreach(var drow in dtr)
{
drow.delete();
}
dtperson.AcceptChanges();
我希望它會幫助你
要從DataTable 中刪除整行,請執行以下操作
DataTable dt = new DataTable(); //User DataTable
DataRow[] rows;
rows = dt.Select("UserName = 'KarthiK'"); //'UserName' is ColumnName
foreach (DataRow row in rows)
dt.Rows.Remove(row);
或者只是將DataTable Row 集合轉換為列表:
foreach(DataRow dr in dtPerson.Rows.ToList())
{
if(dr["name"].ToString()=="Joe")
dr.Delete();
}
<asp:GridView ID="grd_item_list" runat="server" AutoGenerateColumns="false" Width="100%" CssClass="table table-bordered table-hover" OnRowCommand="grd_item_list_RowCommand">
<Columns>
<asp:TemplateField HeaderText="No">
<ItemTemplate>
<%# Container.DataItemIndex + 1 %>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Actions">
<ItemTemplate>
<asp:Button ID="remove_itemIndex" OnClientClick="if(confirm('Are You Sure to delete?')==true){ return true;} else{ return false;}" runat="server" class="btn btn-primary" Text="REMOVE" CommandName="REMOVE_ITEM" CommandArgument='<%# Container.DataItemIndex+1 %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
**This is the row binding event**
protected void grd_item_list_RowCommand(object sender, GridViewCommandEventArgs e) {
item_list_bind_structure();
if (ViewState["item_list"] != null)
dt = (DataTable)ViewState["item_list"];
if (e.CommandName == "REMOVE_ITEM") {
var RowNum = Convert.ToInt32(e.CommandArgument.ToString()) - 1;
DataRow dr = dt.Rows[RowNum];
dr.Delete();
}
grd_item_list.DataSource = dt;
grd_item_list.DataBind();
}
我知道這是一個非常古老的問題,幾天前我也遇到過類似的情況。
問題是,在我的桌子上大約是。 10000 行,因此循環遍歷DataTable
行非常慢。
最后,我找到了更快的解決方案,在該解決方案中,我復制了具有所需結果的源DataTable
,清除源DataTable
並將臨時DataTable
結果merge
到源DataTable
。
注意:而是在名為name
DataRow
搜索Joe
您必須搜索所有沒有姓名Joe
記錄(有點相反的搜索方式)
有例子( vb.net
):
'Copy all rows into tmpTable whose not contain Joe in name DataRow
Dim tmpTable As DataTable = drPerson.Select("name<>'Joe'").CopyToTable
'Clear source DataTable, in Your case dtPerson
dtPerson.Clear()
'merge tmpTable into dtPerson (rows whose name not contain Joe)
dtPerson.Merge(tmpTable)
tmpTable = Nothing
我希望這個更短的解決方案會對某人有所幫助。
有c#
代碼(不確定它是否正確,因為我使用了在線轉換器 :():
//Copy all rows into tmpTable whose not contain Joe in name DataRow
DataTable tmpTable = drPerson.Select("name<>'Joe'").CopyToTable;
//Clear source DataTable, in Your case dtPerson
dtPerson.Clear();
//merge tmpTable into dtPerson (rows whose name not contain Joe)
dtPerson.Merge(tmpTable);
tmpTable = null;
當然,如果沒有結果,我使用了Try/Catch
(例如,如果您的dtPerson
不包含name
Joe
,它將拋出異常),因此您對您的表不做任何操作,它保持不變。
問題出在哪里:禁止在 foreach 循環內從集合中刪除項目。
解決方案:要么像 Widor 寫的那樣做,要么使用兩個循環。 在第一次通過 DataTable 時,您只存儲(在臨時列表中)對要刪除的行的引用。 然后在第二次遍歷臨時列表時刪除這些行。
我的應用程序中有一個數據集,我去設置更改(刪除一行),但ds.tabales["TableName"]
是只讀的。 然后我找到了這個解決方案。
這是一個 wpf C#
應用程序,
try {
var results = from row in ds.Tables["TableName"].AsEnumerable() where row.Field<string>("Personalid") == "47" select row;
foreach (DataRow row in results) {
ds.Tables["TableName"].Rows.Remove(row);
}
}
您嘗試使用此方法從數據表中獲取和刪除 id 列
if (dt1.Columns.Contains("ID"))
{
for (int i = dt1.Rows.Count - 1; i >= 0; i--)
{
DataRow dr = dt1.Rows[i];
if (dr["ID"].ToString() != "" && dr["ID"].ToString() != null)
{
dr.Delete();
}
}
dt1.Columns.Remove("ID");
}
我在這里看到了正確答案的各種零碎部分,但讓我把它們放在一起並解釋一些事情。
首先, AcceptChanges
應該只用於將表上的整個事務標記為已驗證和提交。 這意味着如果您使用 DataTable 作為綁定到 SQL 服務器的數據源,則手動調用AcceptChanges
將保證更改永遠不會保存到 SQL 服務器。
讓這個問題更令人困惑的是,實際上有兩種情況會拋出異常,我們必須防止這兩種情況。
1.修改一個IEnumerable的集合
我們不能向被枚舉的集合添加或刪除索引,因為這樣做可能會影響枚舉器的內部索引。 有兩種方法可以解決這個問題:要么在 for 循環中進行自己的索引,要么使用單獨的集合(未修改)進行枚舉。
2. 嘗試閱讀已刪除的條目
由於數據表是事務性集合,條目可以被標記為刪除,但仍會出現在枚舉中。 這意味着如果您向已刪除的條目詢問列"name"
那么它將引發異常。 這意味着我們必須在查詢列之前檢查是否dr.RowState != DataRowState.Deleted
。
把這一切放在一起
我們可能會變得混亂並手動完成所有這些工作,或者我們可以讓 DataTable 為我們完成所有工作,並通過執行以下操作使語句看起來更像 SQL 調用:
string name = "Joe";
foreach(DataRow dr in dtPerson.Select($"name='{name}'"))
dr.Delete();
通過調用 DataTable 的Select
函數,我們的查詢會自動避免 DataTable 中已刪除的條目。 由於Select
函數返回一個匹配數組,因此在調用dr.Delete()
時不會修改我們正在枚舉的集合。 我還為 Select 表達式添加了字符串插值,以允許在不使代碼嘈雜的情況下進行變量選擇。
在按鈕中使用它的簡單方法:
var table = $('#example1').DataTable();
table.row($(`#yesmediasec-${id}`).closest('tr')).remove( ).draw();
示例 1 = id 表。 yesmediasec = 行中按鈕的 id
使用它,一切都會好的
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.