为什么我需要执行深度克隆才能使此代码正常工作?
以下代码有效。然而,它是有效的,因为我最终创建了供应商的深度克隆。如果我不执行深度克隆,那么我们会收到一条错误,表明供应商对象已更改,并且修改供应商表的尝试失败。仅当运行以下行时才会发生这种情况:foreach(例外情况中的供应商供应商)
。奇怪的是,无论 Delete()
方法是否被执行,都会发生这种情况。为什么会发生这种情况?我已经发布了下面的工作代码供您检查。正如我所说,如果您尝试在没有深度克隆的情况下进行循环,那么它不起作用......有什么想法吗?
public void DeleteSuppliers(IList<Supplier> suppliers, Int32 parentID)
{
// If a supplier has been deleted on the form we need to delete from the database.
// Get the suppliers from the database
List<Supplier> dbSuppliers = Supplier.FindAllByParentID(parentID);
// So return any suppliers that are in the database that are not now on this form
IEnumerable<Supplier> results = dbSuppliers.Where(f => !Suppliers.Any(d => d.Id == f.Id));
IList<Supplier> exceptions = null;
// code guard
if (results != null)
{
// cast as a list
IList<Supplier> tempList = (IList<Supplier>)results.ToList();
// deep clone otherwise there would be an error
exceptions = (IList<Supplier>)ObjectHelper.DeepClone(tempList);
// explicit clean up
tempList = null;
}
// Delete the exceptions from the database
if (exceptions != null)
{
// walk the suppliers that were deleted from the form
foreach (Supplier suppliers in exceptions)
{
// delete the supplier from the database
suppliers.Delete();
}
}
}
The following code works. However, it works because I end up creating a deep clone of the suppliers. If I do not perform a deep clone then we get an error suggesting that the supplier objects have changed and the attempt to amend the supplier table has failed. This only happens if the following line is run: foreach (Supplier suppliers in exceptions)
. Oddly, this occurs irrespective whether the Delete()
method is executed. Why does this happen? I have posted the working code below for your inspection. As I say, if you try looping without deep cloning then it does not work... Any ideas?
public void DeleteSuppliers(IList<Supplier> suppliers, Int32 parentID)
{
// If a supplier has been deleted on the form we need to delete from the database.
// Get the suppliers from the database
List<Supplier> dbSuppliers = Supplier.FindAllByParentID(parentID);
// So return any suppliers that are in the database that are not now on this form
IEnumerable<Supplier> results = dbSuppliers.Where(f => !Suppliers.Any(d => d.Id == f.Id));
IList<Supplier> exceptions = null;
// code guard
if (results != null)
{
// cast as a list
IList<Supplier> tempList = (IList<Supplier>)results.ToList();
// deep clone otherwise there would be an error
exceptions = (IList<Supplier>)ObjectHelper.DeepClone(tempList);
// explicit clean up
tempList = null;
}
// Delete the exceptions from the database
if (exceptions != null)
{
// walk the suppliers that were deleted from the form
foreach (Supplier suppliers in exceptions)
{
// delete the supplier from the database
suppliers.Delete();
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为错误是关于枚举的集合已更改。您不允许更改 foreach 语句枚举的集合(或者枚举 IEnumerable 的任何内容,如果我没记错的话)。
但是,如果您进行克隆,那么您正在枚举的集合与受删除影响的集合是分开的。
你尝试过浅拷贝吗?我认为这也同样有效。可以使用 ToArray 创建浅表副本。
I think the error is about the collection being enumerated having changed. You're not allowed to change the collection being enumerated by a foreach statement (or anything that enumerated an IEnumerable, if I recall correctly).
But if you make a clone then the collection you're enumerating is separate from the collection being affected by the Delete.
Have you tried a shallow copy? I would think that would work just as well. A shallow copy could be created with ToArray.
我通过重新排序执行流程解决了这个问题。本来这段代码是最后执行的。当我第一次执行它时,错误消失了。
I resolved the issue by reordering the execution flow. Originally, this piece of code was execute last. The error went away when I executed it first.