Entity Framework 6 не работает на нескольких задачах - PullRequest
0 голосов
/ 12 марта 2019

У меня есть стандартная система клиент-сервер, позволяющая получать объекты с сервера, обновлять их в клиенте и отправлять обратно на сервер для сохранения (сохранение отключенного объекта).Работает хорошо.Но когда я пытаюсь запустить тот же код с помощью TPL (Task.Run ...), я получаю следующее исключение:

System.InvalidOperationException: на объект сущности нельзя ссылаться несколькими экземплярами IEntityChangeTracker.в System.Data.Entity.Core.Objects.ObjectContext.VerifyContextForAddOrAttach (IEntityWrapper wrappedEntity) в System.Data.Entity.Core.Objects.ObjectContext.AttachSingleObject (IEntityWrapper wraityEntity.jectEntity.DataClasses.RelatedEnd.AddEntityToObjectStateManager (IEntityWrapper wrappedEntity, Boolean doAttach) в System.Data.Entity.Core.Objects.DataClasses.EntityReference.AddEntityToObjectState *мой код на сервере, который я пытаюсь запустить в другой задаче:

using (var dal = UnityManager.Instance.Resolve<IRepositoryDbContextDal>())
{
    dal.Set(entity.GetType()).Attach(entity);
    dal.Entry(entity).State = EntityState.Modified;
    dal.SaveChanges();
}

UnityManager дает мне новый класс, который упаковывает DbContext

1 Ответ

0 голосов
/ 13 марта 2019

Проблема, с которой вы сталкиваетесь, заключается в том, что вы связываете сущности с несколькими активными DbContexts.Обычно это означает, что у вас есть DbContext, который, по вашему мнению, мертв и удален, но его нет.

В качестве простого примера:

Course testCourse = null;
using (var context = new EntityContext())
{
   testCourse = context.Courses.Single(x => x.CourseId == 3);
}
testCourse.Name = "UpdatedTest2";
using (var context = new EntityContext())
{
    context.Courses.Attach(testCourse);
    context.Entry(testCourse).State = EntityState.Modified;
    context.SaveChanges();
}

Приведенный выше код работает.Мы загружаем сущность с одним контекстом, контекст удаляется (конец использования блока), поэтому сущность теперь не отслеживается.Мы можем изменить его, прикрепить к другому DbContext, установить его состояние в «Измененный» и сохранить его.

Теперь возьмите следующий код:

Course testCourse = null;
var openContext = new EntityContext();
testCourse = openContext.Courses.Single(x => x.CourseId == 3);
testCourse.Name = "UpdatedTest2";

using (var context = new EntityContext())
{
    context.Courses.Attach(testCourse);
    context.Entry(testCourse).State = EntityState.Modified;
    context.SaveChanges();
}

Этот код довольно похож, но обратите вниманиечто исходный контекст не расположен.Мы загружаем объект и модифицируем его, но затем пытаемся связать его с другим контекстом для сохранения.Мы получаем исключение для отслеживания изменений нескольких сущностей.

Простое исправление, при котором вы знаете, что контекст не будет удален, и вам определенно нужно связать сущность со вторым контекстом, это явно отделить сущность от оригинала.context:

Course testCourse = null;
var openContext = new EntityContext();
testCourse = openContext.Courses.Single(x => x.CourseId == 3);
openContext.Entry(testCourse).State = EntityState.Detached; // Remove association from original context.
testCourse.Name = "UpdatedTest2";

using (var context = new EntityContext())
{
    context.Courses.Attach(testCourse);
    context.Entry(testCourse).State = EntityState.Modified;
    context.SaveChanges();
}

Однако в большинстве случаев это просто скрывает основную проблему, вокруг которой плавают DbContexts, которые не удаляются.Ключевым моментом здесь является обеспечение удаления любых созданных DbContexts.(using блокирует для любых DbContexts, которые new ed). Если вы используете контейнер IoC, вам нужно прочитать, как они назначают область действия времени для зависимостей, которые они вводят.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...