我想知道为什么DbContext对象上没有Detach方法,就像ObjectContext一样。我只能假设这个遗漏是故意的,但我很难弄清楚原因。我需要能够分离和重新附加实体(例如,在ASP.NET项目中放入缓存)。但是,由于我无法分离实体,当我尝试附加与先前上下文关联的实体时,我得到“实体对象不能被多个IEntityChangeTracker实例引用”异常。
这里有什么指导?我错过了什么吗?
答案 0 :(得分:85)
对于可能偶然发现此问题的人,从CTP5开始,您现在需要编写
((IObjectContextAdapter)context).ObjectContext
以获取ObjectContext。
答案 1 :(得分:37)
DbContext在内部使用ObjectContext,EF团队将其作为 protected 属性提供,以防您需要下拉到较低级别的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; }
...
}
答案 2 :(得分:16)
EF: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是太先进的技术,应该被隐藏”。恕我直言,发明这个的人应该被拍摄 - 因为如果你添加全新的实体,否则很难在没有改变db的情况下删除它(你可以使用DbEntityEntry进行操作,但这是另一个故事)。
使用 EF6 (我不知何故跳过EF5 :))你不再需要detach()
了,因为删除新添加的条目不会像EF4那样生成delete from [table] where [Id] = 0
- 你可以致电mySet.Remove(myFreshlyCreatedAndAddedEntity)
,一切都会好起来的。
答案 3 :(得分:7)
我通常使用属性扩展基类(继承自DbContext):
public class MyDbContext : DbContext
{
public ObjectContext ThisObjectContext
{
get
{
return ((IObjectContextAdapter)this).ObjectContext;
}
}
}
以后你可以将这个属性用于各种有用的东西......比如Detach:)