2010-11-12 72 views
62

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

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

+0

有没有人有什么要说的:“这里有什么指导?我错过了什么?”就我个人而言,我只想在使用Detach的同时寻找解决方案从上下文中读取实体,然后保存从UI返回的实例。这给了我“在ObjectStateManager中已经存在一个具有相同键的对象。ObjectStateManager不能使用同一个键来追踪多个对象。“ – 2013-03-24 15:06:44

回答

85

对于人就这个问题可能会跌倒,如您现在需要编写CTP5

((IObjectContextAdapter)context).ObjectContext 

为了得到ObjectContext。

+1

+1另外你需要引用System.Data.Entity – Pandincus 2011-03-05 18:23:32

+0

+1清洁,优雅,一个班轮,我喜欢它也想抛出,在这里找到的接口具体是:System.Data.Entity.Infrastructure.IObjectContextAdapter和是像Pandincus指出的你还必须参考System.Data.Entity。 – dyslexicanaboko 2013-02-25 22:56:21

38

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; } 
    ... 
} 
+0

@Stacker这不是答案,因为它需要在上面选定的答案中概述的转换,即'DbContext'实现了'IObjectContextAdapter',它给了它'ObjectContext'属性,它是结合2个答案给出了@ splite的答案,低于 – eudaimos 2012-11-19 19:07:07

+1

ChangeObjectState是非常懒惰的,它使用的“线性算法与演员”,这是...排序...你知道... Reeeeally坏 – 2013-04-02 07:43:25

15

EF:CF 4.1 RC1EF: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); 
    } 
} 

微软决定 “拆离太先进的技术,应该被隐藏”。恕我直言,谁发明了这个人应该被枪杀 - 因为如果你添加全新的实体,否则很难删除它没有改变数据库(你可以用DbEntityEntry操作,但这是另一回事)。

编辑4年之后:

随着EF6(我莫名其妙地跳过EF5 :))你不需要再detach(),becouse除去新加入的条目不产生delete from [table] where [Id] = 0在EF4 - 你可以叫mySet.Remove(myFreshlyCreatedAndAddedEntity)和一切都会好起来的。

+0

shot?谁需要该功能呢?:P – quetzalcoatl 2013-02-12 21:32:18

+1

@quetzalcoatl:'var context = ...; var poco = new Poco(); context.Add(POCO); context.Remove(poco);'<---抛出异常,因为你必须分离它,而不是删除 - 嘿,分离隐藏... – 2013-03-29 10:12:12

+1

(5分钟编辑不见了,sry :))那时我是如此生气......当你制作Windows应用程序时,你必须有一些方法来“取消创建新的,可能不完整的条目,但保持UoW上下文”......我们摆脱整个EF顺便说一句,并编写我们自己的ORM:没有办法利用延迟加载(我有一堆的发票,我不能加载每个InvoiceItem在单一“InvoiceId在(xxyy)”查询 - 包括没有工作方式我们预期),更大的存储库sooooo懒(线性(! )在每次执行之前搜索,wtf ...),为100多个poco类型创建代理需要太多时间,等等...... – 2013-03-29 10:26:15

6

我通常与物业扩展基类(从继承的DbContext):

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

后,你可以使用该属性为各种有用的东西......像拆离:)

相关问题