从 DataTable 中删除特定行
我想从 DataTable 中删除一些行,但它给出了这样的错误,
集合已修改;枚举操作可能无法执行
我用于删除此代码的
foreach(DataRow dr in dtPerson.Rows){
if(dr["name"].ToString()=="Joe")
dr.Delete();
}
,那么,问题是什么以及如何修复它?您建议采用哪种方法?
I want to delete some rows from DataTable, but it gives an error like this,
Collection was modified; enumeration operation might not execute
I use for deleting this code,
foreach(DataRow dr in dtPerson.Rows){
if(dr["name"].ToString()=="Joe")
dr.Delete();
}
So, what is the problem and how to fix it? Which method do you advise?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
这对我有用,
This works for me,
要从 DataTable 中删除整行,请执行以下操作
To remove entire row from DataTable , do like this
或者只是将 DataTable Row 集合 转换为列表:
Or just convert a DataTable Row collection to a list:
我在这里看到了正确答案的各种零散部分,但让我将它们放在一起并解释一些事情。
首先,
AcceptChanges
只能用于将表上的整个事务标记为已验证并已提交。这意味着,如果您使用 DataTable 作为数据源来绑定到 SQL 服务器等,那么手动调用AcceptChanges
将保证更改永远不会保存到 SQL 服务器< /强>。使这个问题更令人困惑的是,实际上有两种情况会引发异常,而我们必须阻止这两种情况。
1.修改 IEnumerable 的集合
我们无法向正在枚举的集合添加或删除索引,因为这样做可能会影响枚举器的内部索引。
有两种方法可以解决这个问题:要么在 for 循环中进行自己的索引,要么使用单独的集合(未修改)进行枚举。
2.尝试读取已删除的条目
由于 DataTable 是事务性集合,因此可以将条目标记为删除,但仍会出现在枚举中。这意味着,如果您询问
“name”列的已删除条目
,那么它将引发异常。这意味着我们必须在查询列之前检查是否
dr.RowState != DataRowState.Deleted
。将它们放在一起
我们可能会变得混乱并手动完成所有这些工作,或者我们可以让 DataTable 为我们完成所有工作,并通过执行以下操作使语句看起来更像 SQL 调用:
通过调用DataTable的
Select
函数,我们的查询会自动避免DataTable中已删除的条目。由于Select
函数返回一个匹配数组,因此当我们调用dr.Delete()
时,我们枚举的集合不会被修改。我还通过字符串插值为 Select 表达式增添了趣味,以允许变量选择而不会使代码变得嘈杂。I'm seeing various bits and pieces of the right answer here, but let me bring it all together and explain a couple of things.
First of all,
AcceptChanges
should only be used to mark the entire transaction on a table as being validated and committed. Which means if you are using the DataTable as a DataSource for binding to, for example, an SQL server, then callingAcceptChanges
manually will guarantee that that the changes never get saved to the SQL server.What makes this issue more confusing is that there are actually two cases in which the exception is thrown and we have to prevent both of them.
1. Modifying an IEnumerable's Collection
We can't add or remove an index to the collection being enumerated because doing so may affect the enumerator's internal indexing.
There are two ways to get around this: either do your own indexing in a for loop, or use a separate collection (that is not modified) for the enumeration.
2. Attempting to Read a Deleted Entry
Since DataTables are transactional collections, entries can be marked for deletion but still appear in the enumeration. Which means that if you ask a deleted entry for the column
"name"
then it will throw an exception.Which means we must check to see whether
dr.RowState != DataRowState.Deleted
before querying a column.Putting it all together
We could get messy and do all of that manually, or we can let the DataTable do all the work for us and make the statement look and at more like an SQL call by doing the following:
By calling DataTable's
Select
function, our query automatically avoids already deleted entries in the DataTable. And since theSelect
function returns an array of matches, the collection we are enumerating over is not modified when we calldr.Delete()
. I've also spiced up the Select expression with string interpolation to allow for variable selection without making the code noisy.问题出在哪里:禁止在 foreach 循环内从集合中删除项目。
解决方案:要么像 Widor 写的那样,要么使用两个循环。在第一次传递 DataTable 时,您仅存储(在临时列表中)对要删除的行的引用。然后在第二次遍历临时列表时删除这些行。
Where is the problem: It is forbidden to delete items from collection inside a foreach loop.
Solution: Either do it like Widor wrote, or use two loops. In the first pass over DataTable you only store (in a temporary list) the references to rows you want to delete. Then in the second pass over your temporary list you delete those rows.
我知道这是一个非常老的问题,几天前我也遇到过类似的情况。
问题是,我的表中大约有。 10000 行,因此循环
DataTable
行非常慢。最后,我找到了更快的解决方案,其中我复制了具有所需结果的源
DataTable
,清除源DataTable
并从临时合并
结果>DataTable 进入源一。注意:而是在名为
name
的DataRow
中搜索Joe
,您必须搜索没有名称<的所有记录< code>Joe (相反的搜索方式)有示例(
vb.net
):我希望这个较短的解决方案能够帮助某人。
有
c#
代码(不确定是否正确,因为我使用了在线转换器:( ):当然,我使用了
Try/Catch
以防万一没有结果(例如例如,如果您的dtPerson
不包含name
Joe
它会抛出异常),所以您对您的表不执行任何操作,它保持不变。I know this is, very, old question, and I have similar situation few days ago.
Problem was, in my table are approx. 10000 rows, so looping trough
DataTable
rows was very slow.Finally, I found much faster solution, where I make copy of source
DataTable
with desired results, clear sourceDataTable
andmerge
results from temporaryDataTable
into source one.note : instead search for
Joe
inDataRow
calledname
You have to search for all records whose not have nameJoe
(little opposite way of searching)There is example (
vb.net
) :I hope so this shorter solution will help someone.
There is
c#
code (not sure is it correct because I used online converter :( ):Of course, I used
Try/Catch
in case if there is no result (for example, if YourdtPerson
don't containname
Joe
it will throw exception), so You do nothing with Your table, it stays unchanged.您尝试从数据表中获取和删除 id 列
You try this for getting and removing id column from data table
我的应用程序中有一个数据集,我对其进行了设置更改(删除一行),但 ds.tabales["TableName"] 是只读的。然后我找到了这个解决方案。
这是一个 wpf
C#
应用程序,I have a dataset in my app and I went to set changes (deleting a row) to it but
ds.tabales["TableName"]
is read only. Then I found this solution.It's a wpf
C#
app,最简单的方法是在按钮中使用它:
example1 = id table 。
yesmediasec = 行中按钮的 id
使用它,一切都会好的
the easy way use this in button :
example1 = id table .
yesmediasec = id of the button in the row
use it and every thing will be ok
如果从集合中删除项目,则该集合已更改,并且您无法继续枚举它。
相反,请使用 For 循环,例如:
请注意,您正在反向迭代以避免在删除当前索引后跳过一行。
If you delete an item from a collection, that collection has been changed and you can't continue to enumerate through it.
Instead, use a For loop, such as:
Note that you are iterating in reverse to avoid skipping a row after deleting the current index.
在每个人都加入“您无法删除枚举中的行”的潮流之前,您需要首先认识到数据表是事务性的,并且在调用AcceptChanges()之前,不要从技术上清除更改。
如果您在调用Delete时看到此异常,则您已经处于待更改数据状态。例如,如果您刚刚从数据库加载,并且处于 foreach 循环内,则调用 Delete 会引发异常。
但!但!
如果您从数据库加载行并调用函数“AcceptChanges()”,则您会将所有这些挂起的更改提交到 DataTable。现在,您可以遍历调用Delete() 的行列表,无需担心,因为它只是将行标记为要删除,但直到您再次调用AcceptChanges 时才会提交()
我意识到这个回复有点过时了,但我最近不得不处理类似的问题,希望这能为未来处理 10 年前代码的开发人员减轻一些痛苦:)
Ps 这是一个简单的Jeff 添加的代码示例:
C#
VB.Net
Before everyone jumps on the 'You can't delete rows in an Enumeration' bandwagon, you need to first realize that DataTables are transactional, and do not technically purge changes until you call AcceptChanges()
If you are seeing this exception while calling Delete, you are already in a pending-changes data state. For instance, if you have just loaded from the database, calling Delete would throw an exception if you were inside a foreach loop.
BUT! BUT!
If you load rows from the database and call the function 'AcceptChanges()' you commit all of those pending changes to the DataTable. Now you can iterate through the list of rows calling Delete() without a care in the world, because it simply ear-marks the row for Deletion, but is not committed until you again call AcceptChanges()
I realize this response is a bit dated, but I had to deal with a similar issue recently and hopefully this saves some pain for a future developer working on 10-year-old code :)
P.s. Here is a simple code example added by Jeff:
C#
VB.Net
使用此解决方案:
如果要在删除行后使用数据表,则会收到错误。所以你可以做的是:
将
dr.Delete();
替换为dtPerson.Rows.Remove(dr);
with this solution:
if you are going to use the datatable after deleting the row, you will get an error. So what you can do is:
replace
dr.Delete();
withdtPerson.Rows.Remove(dr);