2011-04-18 55 views
5

我正在爲我的EntityFramework對象創建擴展,如How to: Customize Generated Data Objects中所述,但在一些擴展中,我需要獲取實例的ObjectContext以查找模型中的其他值。我找到了Tip 24 – How to get the ObjectContext from an Entity,但是這是幾年前寫的,這是在similar SO question中引用的,但我真的希望現在有更好的答案。從實體對象獲取ObjectContext引用的最快方法是什麼?

當然,這一定是經常需要的東西,從實體本身檢索實體的對象上下文應該用官方方法來支持。

在此先感謝有關此實施的任何更新信息。

回答

0

不,沒有任何這樣的方法。所描述的解決方法看起來像它被定義爲由於實體從EntityObject得出唯一的選擇:

[Serializable, DataContract(IsReference=true)] 
public abstract class EntityObject : StructuralObject, IEntityWithKey, 
    IEntityWithChangeTracker, IEntityWithRelationships 
{ 
    ... 
} 

據我所知只有IEntityWithRelationships.RelationshipManager導致ObjectContext。這在EF 4中沒有改變。

另外,從實體訪問上下文並不常見。我可以想象這對於在EF之上實現活動記錄模式有幫助,但在這種情況下,您也可能控制在實體的靜態方法內創建上下文,因此您應該能夠將其設置爲實體。在其他情況下,我會說這是你應該儘可能避免的事情。

+0

感謝您的確切答覆,拉迪斯拉夫。我必須不同意你的說法,「這是你應該儘可能避免的事情」。顯然,這是必要的,否則關於如何做的問題和帖子將永遠不會寫出來。有一種方法可以獲得對大多數實體實例的ObjectContext的引用,但效率不高。有許多有效的場景需要從對象本身檢索對象的上下文,特別是需要與實體框架模型當前不支持的數據相關操作的擴展方法。 – 2011-04-19 01:49:46

0

這是我用的;這是一種基於約定的方法,很容易添加到項目中。

首先,添加鉤子到你的對象上下文:

public partial class Database1Entities 
{ 
    partial void OnContextCreated() 
    { 
     this.ObjectMaterialized += (_, e) => 
     { 
      try 
      { 
       dynamic entity = e.Entity; 
       entity.ObjectContext = this; 
      } 
      catch (RuntimeBinderException) 
      { 
      } 
     }; 
     this.ObjectStateManager.ObjectStateManagerChanged += (_, e) => 
     { 
      if (e.Action == CollectionChangeAction.Add) 
      { 
       try 
       { 
        dynamic entity = e.Element; 
        entity.ObjectContext = this; 
       } 
       catch (RuntimeBinderException) 
       { 
       } 
      } 
      else if (e.Action == CollectionChangeAction.Remove) 
      { 
       try 
       { 
        dynamic entity = e.Element; 
        entity.ObjectContext = null; 
       } 
       catch (RuntimeBinderException) 
       { 
       } 
      } 
     }; 
    } 
} 

這將嘗試動態地設置一個名爲ObjectContext上與該對象的上下文相關聯的任何實體屬性。

接下來,添加一個ObjectContext到實體類型:

public partial class Table1 
{ 
    /// <summary> 
    /// Gets or sets the context for this entity. 
    /// This should not be set by end-user code; this property will be set 
    /// automatically as entities are created or added, 
    /// and will be set to <c>null</c> as entities are detached. 
    /// </summary> 
    public Database1Entities ObjectContext { get; set; } 
} 

此解決方案要求一個ObjectContext屬性被添加到每個實體類型。

+0

謝謝你的回覆,斯蒂芬。不幸的是,將這個屬性添加到每個實體類型根本不可行或不可持續。 – 2011-04-25 22:41:23

+0

@John:在這種情況下,請使用連接屬性查看我的其他答案。 – 2011-04-26 03:18:11

3

還有另一種解決方案,使用connected properties

使用連接的屬性應該是這樣的(警告:未經測試的代碼):

public partial class Database1Entities 
{ 
    private struct ObjectContextProperty { } 

    partial void OnContextCreated() 
    { 
     this.ObjectMaterialized += (_, e) => 
     { 
      e.Entity.GetConnectedProperty<Database1Entities, ObjectContextProperty>().Set(this); 
     }; 
     this.ObjectStateManager.ObjectStateManagerChanged += (_, e) => 
     { 
      if (e.Action == CollectionChangeAction.Add) 
      { 
       e.Element.GetConnectedProperty<Database1Entities, ObjectContextProperty>().Set(this); 
      } 
      else if (e.Action == CollectionChangeAction.Remove) 
      { 
       e.Element.GetConnectedProperty<Database1Entities, ObjectContextProperty>().Set(null); 
      } 
     }; 
    } 

    /// <summary> 
    /// Gets the object context for the entity. Returns <c>null</c> if the entity is detached. 
    /// </summary> 
    /// <param name="entity">The entity for which to return the object context.</param> 
    public static Database1Entities FromEntity(EntityObject entity) 
    { 
     return entity.GetConnectedProperty<Database1Entities, ObjectContextProperty>().GetOrConnect(null); 
    } 
} 

然後你可以使用Database1Entities.FromEntity擺脫實體對象的對象範圍內。對實體對象是可選的

public partial class Table1 
{ 
    /// <summary> 
    /// Gets the object context for this entity. Returns <c>null</c> if the entity is detached. 
    /// </summary> 
    public Database1Entities ObjectContext { get { return Database1Entities.FromEntity(this); } } 
} 

在這種解決方案中,ObjectContext屬性:您還可以定義在實體對象的實際屬性,以及如果你想要的。

+0

謝謝。我會研究一下連接的屬性,看看這個項目是否有意義。我很感謝你回答這個問題的時間。 – 2011-04-26 23:39:04

+0

良好的工作,你也可以使用擴展方法來添加一個方法,如GetObjectContext到所有的entityObjects。 public static Database1Entities GetObjectContext(this EntityObject entityObject) { return Database1Entities.FromEntity(entityObject); } – MNZ 2012-02-20 12:24:22

相關問題