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