实体框架代码优先 - DbContext上没有Detach()方法

时间:2010-11-12 18:55:31

标签: entity-framework code-first

我想知道为什么DbContext对象上没有Detach方法,就像ObjectContext一样。我只能假设这个遗漏是故意的,但我很难弄清楚原因。我需要能够分离和重新附加实体(例如,在ASP.NET项目中放入缓存)。但是,由于我无法分离实体,当我尝试附加与先前上下文关联的实体时,我得到“实体对象不能被多个IEntityChangeTracker实例引用”异常。

这里有什么指导?我错过了什么吗?

4 个答案:

答案 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进行操作,但这是另一个故事)。

4年后编辑:

使用 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:)