I've written an extension method to add items to an (EF) EntityCollection. I got an interesting error, saying that my collection of IEnumerable ("items") had been modified, after the first loop in the foreach. When I turn items into items.ToList() (like in the code below), it works fine.
I completely understand that doing ToList() will produce a copy of the items on which the foreach will then operate.
What I do NOT understand is what is modifying the IEnumerable when I'm doing a foreach over it.
Update: Somehow, it seems the items variable is the same as the collections variable?
Update 2: I think collection and entity may be affected by EF's entity tracking, but I still fail to understand why
Usage:
ssp.ServiceAreas.ReplaceCollection(model.ServiceAreas);
Here's my extension method:
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);
}
collection.Remove(collection.First(c => c.ID == item.ID));
you are removing in the collection you are iterating.
I created the following sample code:
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);
}
}
This works as you would expect, there are no errors. So in essence, none of the lines are causing issues.
What will cause issues is if you call the list on itself:
one.AddOrUpdate(one);
So from what I can see, you must be calling this extension method with the same collection as both arguments.
If you are, then both Remove
or Add
will mutate the collection and cause this exception.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With