我在想为什么DbContext对象中没有像ObjectContext那样的Detach方法。我只能假设这个省略是有意的,但我很难理解为什么要这样做。例如,在ASP.NET项目中将实体放入缓存时,我需要能够分离和重新附加实体。然而,由于我不能分离实体,在尝试附加先前与另一个上下文相关联的实体时,会引发“实体对象无法被IEntityChangeTracker的多个实例引用”的异常。
这里该怎么办?我是否遗漏了什么重要指导?
这里该怎么办?我是否遗漏了什么重要指导?
对于可能遇到这个问题的人,从 CTP5 开始,现在需要编写以下代码:
((IObjectContextAdapter)context).ObjectContext
为了获得 ObjectContext。DbContext内部使用一个ObjectContext,EF团队将其作为受保护的属性提供,以防您需要降级到更低级别的API,这似乎是这里的情况,因此您可以从派生的DbContext中使用或公开所需的功能:
public class YourContext : DbContext
{
public void Detach(object entity)
{
ObjectContext.Detach(entity);
}
}
你可以从你的控制器中调用这个方法来分离一个实体。
或者,你可以将其改为具有更丰富的 API:
public class YourContext : DbContext
{
public void ChangeObjectState(object entity, EntityState entityState)
{
ObjectContext.ObjectStateManager.ChangeObjectState(entity, entityState);
}
}
这是从元数据中查看 DbContext 的方式:
public class DbContext : IDisposable
{
protected System.Data.Objects.ObjectContext ObjectContext { get; }
...
}
DbContext
实现了 IObjectContextAdapter
,从而赋予了它 ObjectContext
属性,否则无法访问。将这两个答案结合起来得到 @splite 的答案。 - eudaimosEF:CF 4.1 RC1和EF:CF 4.1 RTW具有相同的显式实现IObjectContextAdapter:
public static class DbContextExtensions
{
public static void Detach(this System.Data.Entity.DbContext context, object entity)
{
((System.Data.Entity.Infrastructure.IObjectContextAdapter)context).ObjectContext.Detach(entity);
}
}
微软决定“分离(Detach)是太先进的技术,应该被隐藏”。在我看来,发明这个东西的人应该被枪毙——因为如果你添加了一个全新的实体,否则很难仅仅移除它而不提交更改到数据库(你可以使用DbEntityEntry进行操作,但这是另一回事)。
使用EF6(我不知道怎么跳过了EF5 :) ),你不再需要detach()
,因为删除新添加的条目不会像EF4那样生成delete from [table] where [Id] = 0
- 你只需要调用mySet.Remove(myFreshlyCreatedAndAddedEntity)
,一切都会没问题。
var context = ...; var poco = new Poco(); context.Add(poco); context.Remove(poco);
<--- 抛出异常,因为你需要将其 DETACH,而不是 REMOVE - 嘿,DETACH 被隐藏了... - Jan 'splite' K.DbContext
上附加许多对象,有些对象需要被分离,并释放这些对象占用的内存。 - AechoLiu我通常通过继承自DbContext的基类,并使用以下属性进行扩展:
public class MyDbContext : DbContext
{
public ObjectContext ThisObjectContext
{
get
{
return ((IObjectContextAdapter)this).ObjectContext;
}
}
}