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

c# entity-framework entity-framework-6

Question

Our web application accesses data using Entity Framework (db is Oracle). Recently, we switched to EF6. We employ transactions as follows:

  1. We create transactions, and as a result,EntityTransaction thing andEntityConnection right now.
  2. Multiple requests are made to the database at once. Running in its own thread is each request (actually requests come from client). Each request has its own.ObjectContext uses the same process to makeEntityConnection Transaction requests only partially run in parallel, hence there are rarely any parallel requests running at any given time.

And under these circumstances, odd errors started to happen: One exceptionCollection was modified; enumeration operation may not execute .

It can also occur when an EntityTransaction's Connection property is accessed when data are read or changed.

The start of a stack trace can change, but the conclusion 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 option for the stack trace's conclusion, but as you can see, they are essentially 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.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 can be seen, the mistake is inDbInterceptionContext constructor. It resembles EF internals, and the modified collection is an internal collection with no connections to our custom code.

Few notes:

  • This error didn't exist before the EF6 release.
  • Only about 1% of transactions experience an error.

What is the cause of this mistake? Is there a problem with EF6? Or are we misusing EF in some other way? Is it possible to construct manyObjectContext -s for a single connection that is intended to run simultaneously?

I can offer some samples of entire call stacks if necessary.

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

Popular Answer

If you add or remove items from a collection while iterating through it, this issue will arise:

// 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);
}

Perhaps the EF 6 code produces IEnumerable while your older code returned arrays? You should look for this issue in your Create/Update/Delete usecases.

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