I'm finding this same problem with dotConnect v9.5.520 and EF Core 2.0.3 running a simple expression of the type:
Code: Select all
_dbContext.Table.Include(t => t.FkRecords).Single(t => t.Pk == key);
Resulting in an exception like:
Code: Select all
System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
at System.Collections.Generic.List`1.Enumerator.MoveNext()
at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source)
at Microsoft.EntityFrameworkCore.Query.Sql.DefaultQuerySqlGenerator.VisitSelect(SelectExpression selectExpression)
at ¿¿.VisitSelect(SelectExpression )
at Microsoft.EntityFrameworkCore.Query.Expressions.SelectExpression.Accept(ExpressionVisitor visitor)
at Remotion.Linq.Parsing.ThrowingExpressionVisitor.Visit(Expression expression)
at ¿¿.Visit(Expression )
at Microsoft.EntityFrameworkCore.Query.Sql.DefaultQuerySqlGenerator.GenerateSql(IReadOnlyDictionary`2 parameterValues)
at ¿¿.GenerateSql(IReadOnlyDictionary`2 )
at Microsoft.EntityFrameworkCore.Query.Internal.ShaperCommandContext.GetRelationalCommand(IReadOnlyDictionary`2 parameters)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.BufferlessMoveNext(Boolean buffer)
at Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions.<>c__DisplayClass12_0`2.<Execute>b__0(DbContext c, TState s)
at Microsoft.EntityFrameworkCore.Storage.Internal.NoopExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
at Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions.Execute[TState,TResult](IExecutionStrategy strategy, Func`2 operation, Func`2 verifySucceeded, TState state)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
at Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.IncludeCollection(Int32 includeId, INavigation navigation, INavigation inverseNavigation, IEntityType targetEntityType, IClrCollectionAccessor clrCollectionAccessor, IClrPropertySetter inverseClrPropertySetter, Boolean tracking, Object entity, Func`1 relatedEntitiesFactory)
at lambda_method(Closure , QueryContext , Gallery , Object[] )
at Microsoft.EntityFrameworkCore.Query.Internal.IncludeCompiler._Include[TEntity](QueryContext queryContext, TEntity entity, Object[] included, Action`3 fixup)
at lambda_method(Closure , Gallery )
at System.Linq.Enumerable.SelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
at lambda_method(Closure , QueryContext )
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass17_1`1.<CompileQueryCore>b__0(QueryContext qc)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.Single[TSource](IQueryable`1 source, Expression`1 predicate)
My application runs this same query concurrently (4 - 8 simultaneous threads) but from
distinct DbContext instances, each with their own dedicated DbConnection, so there should be no risk of corrupting state unless either EFCore or dotConnect is keeping static data somewhere and this is getting manipulated whilst EFCore is iterating through the records.
To reproduce ensure you have a machine with at least 4 logical processors available (check your Environment.ProcessorCount, but the higher this is the more likely you are of finding the issue) and run something along the lines of:
Code: Select all
for (int i = 0; i < 1000; ++i)
{
Task.Run(() =>
{
using (var dbContext = new YourDbContext(new DbConnection()))
{
var result = dbContext.Table.Include(t => t.FkRecords).Single(t => t.Pk == key);
}
});
}
You might need to simulate some more work before disposing of the context like that but hopefully you get the idea.