dotConnect с EntityFramework Ядро возвращает Коллекция была изменена; операция перечисления может не выполняться

У меня есть приложение, использующее ASP.Net Core RC2 и Entity Framework Core RC2 и использующее драйвер dotConnect для Oracle (dotConnect пока не поддерживает EF Core 1.0).

Я пытаюсь запустить 8 GET одновременно для разных записей, и я получаю эту ошибку:

Исключение типа "System.InvalidOperationException" произошло в Microsoft.EntityFrameworkCore.dll, но не было обработано в коде пользователя

Дополнительная информация: коллекция была изменена; Операция перечисления может не выполняться.

Исключение выдается из этой строки метода Get на контроллере:

return Ok(_context.Blogs.Include(blog => blog.Posts).FirstOrDefault(blog => blog.Id == id));

Я нашел много вопросов по этому вопросу, но обычно проблема заключается в том, что несколько потоков используют один и тот же экземпляр объекта или изменяют объект во время итерации, но, похоже, ни один из них не имеет здесь значения.

Я добавляю контекст БД в Startup.cs через внедрение зависимостей:

services.AddDbContext<BlogsModel.Model>();

Каждый вызов имеет свой собственный контроллер и экземпляр контекста, который я проверял, выводя оба хэша:

[HttpGet("{id}")]
public IActionResult Get(int id)
{
    Console.WriteLine($"{GetHashCode()} - {_context.GetHashCode()}");
    return Ok(_context.Blogs.Include(blog => blog.Posts).FirstOrDefault(blog => blog.Id == id));
}

Если я уберу часть "Включить" и получу только блог, она будет работать нормально.

[HttpGet("{id}")]
public IActionResult Get(int id)
{
    Console.WriteLine($"{GetHashCode()} - {_context.GetHashCode()}");
    return Ok(_context.Blogs.FirstOrDefault(blog => blog.Id == id));
}

Я также попробовал асинхронную версию, но я все еще получаю ошибку:

[HttpGet("{id}")]
public IActionResult Get(int id)
{
    Console.WriteLine($"{GetHashCode()} - {_context.GetHashCode()}");
    var task = _context.Blogs.Include(blog => blog.Posts).FirstOrDefaultAsync(blog => blog.Id == id);
    task.Wait();
    return Ok(task.Result);
}

Модель очень проста:

create table BLOGS
(
  id   NUMBER not null,
  name VARCHAR2(200) not null
);
alter table BLOGS
  add constraint PK_BLOGS primary key (ID);

create table POSTS
(
  id      NUMBER not null,
  blog_id NUMBER not null,
  title   VARCHAR2(200) not null,
  content VARCHAR2(500) not null
);

alter table POSTS
  add constraint PK_POSTS primary key (ID);
alter table POSTS
  add constraint FK_POSTS_BLOG foreign key (BLOG_ID)
  references BLOGS (ID);

declare
  blogId number := 0;
  postId number := 0;
begin
  for x in 1..1000 loop
    blogId := blogId + 1;
    insert into blogs values (blogId, 'Blog ' || blogId);
    for x in 1..5 loop
      postId := postId + 1;
      insert into posts values (postId, blogId, 'Post ' || postId, 'Content for post ' || postId);
    end loop;
  end loop;
  commit;
end;
/

Полный код для контроллера:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using BlogsModel;
using Microsoft.EntityFrameworkCore;

namespace BlogOracle.Controllers
{
    [Route("api/[controller]")]
    public class BlogsController : Controller
    {
        private Model _context;

        public BlogsController(Model context)
        {
            _context = context;
        }

        // GET api/values/5
        [HttpGet("{id}")]
        public IActionResult Get(int id)
        {
            Console.WriteLine($"{GetHashCode()} - {_context.GetHashCode()}");
            return Ok(_context.Blogs.Include(blog => blog.Posts).FirstOrDefault(blog => blog.Id == id));
        }
    }
}

И стек вызовов:

   at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
   at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
   at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source)
   at Microsoft.EntityFrameworkCore.Query.Expressions.SelectExpression.GetProjectionTypes()
   at Microsoft.EntityFrameworkCore.Query.Sql.DefaultQuerySqlGenerator.CreateValueBufferFactory(IRelationalValueBufferFactoryFactory relationalValueBufferFactoryFactory, DbDataReader dataReader)
   at Microsoft.EntityFrameworkCore.Internal.NonCapturingLazyInitializer.EnsureInitialized[TParam,TValue](TValue& target, TParam param, Func`2 valueFactory)
   at Microsoft.EntityFrameworkCore.Query.Internal.ShaperCommandContext.NotifyReaderCreated(DbDataReader dataReader)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable.Enumerator.MoveNext()
   at Microsoft.EntityFrameworkCore.Query.Internal.IncludeCollectionIterator.<GetRelatedValues>d__4.MoveNext()
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.Include(QueryContext queryContext, Object entity, IReadOnlyList`1 navigationPath, IReadOnlyList`1 relatedEntitiesLoaders, Int32 currentNavigationIndex, Boolean queryStateManager)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.Include(QueryContext queryContext, Object entity, IReadOnlyList`1 navigationPath, IReadOnlyList`1 relatedEntitiesLoaders, Boolean queryStateManager)
   at Microsoft.EntityFrameworkCore.Query.QueryMethodProvider.<_Include>d__30`1.MoveNext()
   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
   at lambda_method(Closure , QueryContext )
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass19_1`1.<CompileQuery>b__1(QueryContext qc)
   at BlogOracle.Controllers.BlogsController.Get(Int32 id) in c:\Projetos\dotnet\BlogOracle\src\BlogOracle\Controllers\BlogsController.cs:line 26
   at lambda_method(Closure , Object , Object[] )
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionAsync>d__6.MoveNext()

Полный код здесь: https://github.com/ricsmania/BlogsOracleEntityFramework

Я делаю что-то не так или это может быть ошибка с компонентом?

0 ответов

Другие вопросы по тегам