我有一个标准的客户端-服务器系统,可以使用从服务器获取实体,在客户端中对其进行更新并发送回服务器以进行保存(断开连接的实体保存)。 效果很好。 但是,当我尝试使用TPL(Task.Run ...)运行相同的代码时,出现以下异常:
System.InvalidOperationException:实体对象不能为 由IEntityChangeTracker的多个实例引用。在 System.Data.Entity.Core.Objects.ObjectContext.VerifyContextForAddOrAttach(IEntityWrapper wrapEntity)在 System.Data.Entity.Core.Objects.ObjectContext.AttachSingleObject(IEntityWrapper wrapEntity,EntitySetentitySet) System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.AddEntityToObjectStateManager(IEntityWrapper wrapEntity,布尔值doAttach)在 System.Data.Entity.Core.Objects.DataClasses.EntityReference.AddEntityToObjectStateManager(IEntityWrapper wrapEntity,布尔值doAttach)位于...
这是我在服务器中尝试运行在其他任务中的代码:
using (var dal = UnityManager.Instance.Resolve<IRepositoryDbContextDal>())
{
dal.Set(entity.GetType()).Attach(entity);
dal.Entry(entity).State = EntityState.Modified;
dal.SaveChanges();
}
UnityManager给我一个包装DbContext的新类
答案 0 :(得分:0)
您面临的问题是您正在跨多个活动DbContext关联实体。通常,这意味着您有一个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();
}
此代码非常相似,但请注意,原始上下文并未处理。我们加载该实体并对其进行修改,但随后尝试将其与另一个上下文关联以进行保存。我们得到了多实体变更跟踪器异常。
您知道不会处理上下文的简单解决方法,并且您确实确实需要将实体与第二个上下文相关联,是将实体与原始上下文明确分离:
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();
}
但是,在大多数情况下,这只是隐藏了您无法解决的DbContext潜在问题。此处的关键是确保处置创建的所有DbContext。 (using
阻止了new
建立的任何DbContext)如果您使用的是IoC容器,则需要了解它们如何将生存期作用域分配给它们注入的依赖项。