实体框架 - 包含/参考/集合

时间:2013-08-06 05:14:40

标签: c# entity-framework navigation-properties

我想知道为什么有单独的方法来填充导航属性。

如果我在整套工作,我可以在一个属性或集合上调用Include

但是,如果我处理单个实体,则根据项目是集合(Collection)还是单个引用(Reference),有两种不同的方法可以调用。

有没有办法解决这个问题 - 这使得事情变得比我想象的更复杂。有谁可以解释为什么在设计EF时决定了这个?

修改

进一步研究,问题更深入。我试图做的是创建一种在单个实体上加载集合/导航属性的通用方法。使用Include可以在整个集合上轻松完成。但ReferenceCollection的方法签名略有不同。

没关系,必须在我的应用程序周围分散这些调用。

e.g。

dbSet<T>().Include(e => e.Property).Include(e => e.Collection).Include(e => e.Collection.Property) 
似乎一切正常。

然而,对单个实体的调用是不同的:

context.Entry(entity).Reference(e => e.Property).Load();
context.Entry(entity).Reference(e => e.Property.Select(e => e.SubProperty)).Load();
context.Entry(entity).Collection(e => e.Collection).Load();

3 个答案:

答案 0 :(得分:13)

Include()方法的唯一目的是在查询时明确地加载相关数据。

另一方面,Entry()方法旨在让您对附加到上下文的实体的当前状态进行特定控制,而不仅仅是Load()相关数据。

这就是为什么你必须在CollectionReferenceProperty方法之间明确选择的原因,每个方法都暴露不同的功能集(因此返回不同的类型),例如:

  • 标量DbPropertyEntry)包含IsModified属性,表示值是否从&#39; x&#39;到了&#39; (例如)。

  • 参考DbReferenceEntry)包含IsLoaded属性,表示数据是否已从数据库加载(而不是&#39; Scalar& #39;财产进入)。

  • 参考集合DbCollectionEntry)派生自ICollection(因此也IEnumberable),这意味着您可以对其进行迭代。数据。但是,它不能包含IsModified属性,因为它可能对集合中的每个项目都有所不同。

但是,如果你只对Load()感兴趣,你可以利用多态Member()方法(返回DbMemberEntry,它是所有上述类的基类)并检查条目是否为“可加载的”

var memberEntry = this.Entry(entity).Member("NavigationProperty");

if (memberEntry is DbCollectionEntry)
    ((DbCollectionEntry)memberEntry).Load();

if (memberEntry is DbReferenceEntry)
    ((DbReferenceEntry)memberEntry).Load();

答案 1 :(得分:5)

你可以这样做:

1.-加载包含馆藏的实体:

MyClass myObject = dbContext.MyClasses
                    .Include(cls => cls.ObjectCollection)
                    .Single(cls => cls.Pk == entityPk);

2.-然后您必须检索该对象Entry并告诉EF在集合对象中加载所需的属性:

dbContext.Entry(myObject).Collection("ObjectCollection").Query().Include("ReferenceClass").Load(); 

进一步阅读:

http://msdn.microsoft.com/en-us/data/jj574232#explicitFilter

答案 2 :(得分:0)

您还可以使用Select加载引用的集合。

db.MyObject.Include(x => x.RefObect.Select(y => y.RefRefObject));