`Collection was modified; enumeration operation may not execute` error while reading data

c# entity-framework entity-framework-6

Question

We have a web-application and it uses Entity framework to access data (db is Oracle). We've moved to EF6 recently. We use transactions in a following way:

  1. We create transaction, so we have EntityTransaction object and EntityConnection object now.
  2. Several concurrent requests are done to DB. Each request runs in its own thread (actually requests come from client). For each request its own ObjectContext is created using the same EntityConnection object. Requests of transaction run in parallel partially, so in a given moment of time there are few parallel running requests.

And under these conditions strange error started to occur: Exception - Collection was modified; enumeration operation may not execute.

It happens when data are read or updated, and even when Connection property of EntityTransaction is accessed.

The beginning of stack trace may vary, but the end is always the same:

System.InvalidOperationException: Collection was modified; enumeration operation may not execute. at System.Collections.Generic.List1.Enumerator.MoveNextRare() at System.Linq.Enumerable.WhereSelectListIterator2.MoveNext() at System.Linq.Enumerable.d__142.MoveNext() at System.Linq.Enumerable.<DistinctIterator>d__811.MoveNext() at System.Linq.Enumerable.WhereEnumerableIterator1.MoveNext() at System.Collections.Generic.List1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source) at System.Data.Entity.Infrastructure.Interception.DbInterceptionContext..ctor(IEnumerable`1 copyFrom) at System.Data.Entity.Core.EntityClient.EntityTransaction.get_InterceptionContext()

Actually there is another variant for the end of stack trace (but as you can see they are basically equivalent):

System.InvalidOperationException: Collection was modified; enumeration operation may not execute. at System.Collections.Generic.List1.Enumerator.MoveNextRare() at System.Linq.Enumerable.WhereSelectListIterator2.MoveNext() at System.Linq.Enumerable.Any[TSource](IEnumerable1 source, Func2 predicate) at System.Data.Entity.Infrastructure.Interception.DbInterceptionContext..ctor(IEnumerable`1 copyFrom) at System.Data.Entity.Core.EntityClient.EntityConnection.get_InterceptionContext()

As we can see, the error occurs in DbInterceptionContext constructor. It's a kind of EF internals and the collection (which is modified) is an internal collection and has no direct link to our custom code.

Few notes:

  • We didn't have such error prior to EF6 update.
  • Error happens relatively rare, for about 1% of transactions.

What is the reason for this error? Is it an issue with EF6? Or we are using EF in a wrong way? Is it allowed to create several ObjectContext-s for one connection which are supposed to run concurrently?

If it is needed I can provide some examples of complete call stacks.

1
3
1/26/2016 3:20:35 PM

Popular Answer

This problem happens if you add/remove to a collection while iterating over it:

// throws "collection was modified" error
foreach (var item in myCollection) {
    myCollection.Remove(item);
}

// to fix this problem, iterate over a copy of the collection whose count does not change
var fixedSize = myCollection.ToArray();
foreach (var item in fixedSize) {
    myCollection.Remove(item);
}

Maybe your old code returned arrays, whereas the EF 6 code returns IEnumerable? You should check your Create/Update/Delete usecases for this problem.

2
1/18/2016 11:11:48 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow