代码之家  ›  专栏  ›  技术社区  ›  Brian Sullivan

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

  •  62
  • Brian Sullivan  · 技术社区  · 14 年前

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

    这里有什么指导?我遗漏了什么吗?

    4 回复  |  直到 14 年前
        1
  •  85
  •   Joakim    14 年前

    对于可能会偶然发现这个问题的人,从CTP5开始,您现在需要编写

    ((IObjectContextAdapter)context).ObjectContext
    

        2
  •  37
  •   Morteza Manavi    14 年前

    DbContext在内部使用ObjectContext,EF team将其作为 受保护的

    public class YourContext : DbContext 
    {
        public void Detach(object entity) 
        {
            ObjectContext.Detach(entity);            
        }
    }
    

    然后可以从控制器调用此方法来分离实体。

    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; }
        ...
    }
    
        3
  •  16
  •   Jan 'splite' K.    8 年前

    参考:CF 4.1 RC1 参考: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进行操作,但那是另一回事)。

    4年后编辑:

    (我不知怎么跳过了EF5:))你不需要 detach() delete from [table] where [Id] = 0 就像EF4一样-你可以打电话给 mySet.Remove(myFreshlyCreatedAndAddedEntity) 一切都会好起来的。

        4
  •  7
  •   Stefan Michev    11 年前

    我通常使用属性扩展基类(继承自DbContext):

    public class MyDbContext : DbContext
    {
        public ObjectContext ThisObjectContext
        {
            get
            {
                return ((IObjectContextAdapter)this).ObjectContext;
            }
        }
    }