2011-04-18 58 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

相关问题