2010-11-12 90 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; 
     } 
    } 
} 

後,你可以使用該屬性爲各種有用的東西......像拆離:)

相關問題