C# 修改IEnumerable神秘,什么是修改我的IEnumerable?
我已经编写了一个扩展方法来向(EF)EntityCollection添加项。我得到一个有趣的错误,说我的IEnumerable(“items”)集合在foreach中的第一个循环之后被修改了。当我将items转换为items.ToList()时(如下面的代码中所示),它可以正常工作 我完全理解执行ToList()将生成foreach随后将操作的项目的副本 我不明白的是,当我对IEnumerable进行foreach时,是什么在修改它 更新:不知何故,items变量似乎与collections变量相同 更新2:我认为集合和实体可能会受到EF实体跟踪的影响,但我仍然无法理解为什么 用法:C# 修改IEnumerable神秘,什么是修改我的IEnumerable?,c#,extension-methods,ienumerable,C#,Extension Methods,Ienumerable,我已经编写了一个扩展方法来向(EF)EntityCollection添加项。我得到一个有趣的错误,说我的IEnumerable(“items”)集合在foreach中的第一个循环之后被修改了。当我将items转换为items.ToList()时(如下面的代码中所示),它可以正常工作 我完全理解执行ToList()将生成foreach随后将操作的项目的副本 我不明白的是,当我对IEnumerable进行foreach时,是什么在修改它 更新:不知何故,items变量似乎与collections变量
ssp.serviceares.ReplaceCollection(model.serviceares)代码>
以下是我的扩展方法:
public static void AddOrUpdate<TEntity>(this EntityCollection<TEntity> collection, IEnumerable<TEntity> items)
where TEntity : EntityObject, IProjectIdentity<int>, new()
{
foreach (var item in items.ToList())
collection.AddOrUpdate(item);
}
public static void AddOrUpdate<TEntity>(this EntityCollection<TEntity> collection, TEntity item)
where TEntity : EntityObject, IProjectIdentity<int>, new()
{
if (item.ID > 0 && collection.Any(c => c.ID == item.ID))
collection.Remove(collection.First(c => c.ID == item.ID));
// For now, the Remove NEVER gets hit
collection.Add(item);
}
publicstaticvoidaddorupdate(此EntityCollection集合,IEnumerable项)
其中tenty:EntityObject,iprojectdentity,new()
{
foreach(items.ToList()中的var item)
收集、添加或更新(项目);
}
公共静态无效添加或更新(此EntityCollection集合,TEntity项)
其中tenty:EntityObject,iprojectdentity,new()
{
if(item.ID>0&&collection.Any(c=>c.ID==item.ID))
collection.Remove(collection.First(c=>c.ID==item.ID));
//现在,移除永远不会被击中
集合。添加(项目);
}
您正在迭代的集合中删除。也许EntityCollection
不喜欢有人接管它的元素?因此,当您添加到集合
时,项目将从项目
中删除
或者可能是items==collection
我创建了以下示例代码:
internal class Program
{
private static void Main(string[] args)
{
var one = new List<string> {"Adam", "John"};
var two = new List<string> {"Adam", "Houldsworth"};
one.AddOrUpdate(two);
Console.Read();
}
}
static class Extensions
{
public static void AddOrUpdate(this IList<string> collection, IEnumerable<string> items)
{
foreach (var item in items.ToList())
collection.AddOrUpdate2(item);
}
public static void AddOrUpdate2(this IList<string> collection, string item)
{
if (collection.Any(c => c == item))
collection.Remove(collection.First(c => c == item));
collection.Add(item);
}
}
因此,从我看到的情况来看,您必须使用与两个参数相同的集合调用此扩展方法
如果是,则Remove
或Add
都会改变集合并导致此异常。可能是第一个项目始终是新项目,因此默认情况下ID设置为某个初始值。然后将其添加到集合中,让EntityFramework生成一个新ID并将其分配给第一个添加的项
然后可能是EntityCollection认为它已经更改了,因为它使用ID在内部进行排序或其他操作。因此,foreach操作(可能使用相同的列表)抛出异常。这也是为什么Adam Houldsworth证明的测试用例没有给出问题 EntityCollection客户=新EntityCollection();
EntityCollection<Customer> customers = new EntityCollection<Customer>();
Customer newCustomer = new Customer() {ID = 0};
customers.Add(newCustomer);
customers.AddOrUpdate(customers);
客户newCustomer=newCustomer(){ID=0};
customers.Add(newCustomer);
customers.AddOrUpdate(客户);
Remove
修改它,add也修改它。@vcsjones虽然这是真的,但在这种情况下它并不是那么简单。在您的情况下,items==collection
吗?您正在从您要访问的集合中添加/删除项(第一个方法为foreach块中的每个项目调用第二个方法,第二个方法是加载/删除内容)。第一个:如何将“项目”与“集合”相同?第二个:删除实际上从未命中,我将更新帖子。但迭代是通过不同的集合(项目)进行的事实上,我对此进行了升级,但在尝试时,这不会导致任何问题。谢谢,但无论是否使用.ToList(),此功能都有效。这仅仅是因为集合和项目确实是不同的对象。我认为我的集合对象可能会受到EF跟踪机制的影响,将再次更新帖子。:-)@sebastiaan是的,我注意到它在没有ToList
的情况下也能工作,但我保持它与您提供的代码类似,以演示问题的来源。
one.AddOrUpdate(one);
EntityCollection<Customer> customers = new EntityCollection<Customer>();
Customer newCustomer = new Customer() {ID = 0};
customers.Add(newCustomer);
customers.AddOrUpdate(customers);