Entity Framework 3.5 - 如何加载孩子

Posted

技术标签:

【中文标题】Entity Framework 3.5 - 如何加载孩子【英文标题】:Entity Framework 3.5 - How to load children 【发布时间】:2010-11-25 08:54:51 【问题描述】:

我的问题可能很简单,你如何加载子类/子类。我找不到任何“负载”或类似的东西来让上下文加载孩子。

上下文类是ObjectContext类型,见下文:

public partial class RTIPricingEntities : global::System.Data.Objects.ObjectContext

产品

Product.ModifiedByUser(加载产品时如何加载这个类??)

Product.Category(加载产品时如何加载分类?)

【问题讨论】:

这是我如何加载数据的示例: 也许我应该提到我正在为 silverlight 应用程序编写此代码。这是通过域服务。 RTIPricingContext _context = new RTIPricingContext(); LoadOperation op = _context.Load(context.GetPurchaseOrderQuery(), PurchaseOrdersLoadedCallback, null);私人无效 PurchaseOrdersLoadedCallback(LoadOperation lo) IEnumerable po = lo.Entities.Where(w => w.UserID == SelectedUser.ID); // 这是我需要在其上填充子类的集合。 【参考方案1】:

我注意到 Craig 的上述解决方案没有同时加载 ModifiedByUser 和 Category。它只加载最后一个对象集合,在这种情况下是“类别”。

var q = from p in Context.Products
              .Include("ModifiedByUser")
              .Include("Category")
    select p;

但是,如果您交换订单以使其成为.Include("Category").Include("ModifiedByUser"),则加载ModifiedByUser。奇怪的是,两个对象集合的IsLoaded 属性都将显示“true”,但是第一个对象集合的计数始终为零。不知道为什么会这样。

【讨论】:

【参考方案2】:

您可以预先加载:

var q = from p in Context.Products
                  .Include("ModifiedByUser")
                  .Include("Category")
        select p;

...或项目:

var q = from p in Context.Products
        select new 
        
           Id = p.Id,
           Name = p.Name
           ModifiedByUserName = p.ModifiedByUser.Name,
           CategoryName = p.Category.Name
        

投影的优点是您只获得所需的数据,而不是每个引用实体的全部。急切加载的优点是返回的实体会进行更改跟踪。为手头的问题选择正确的技术。

更新

是的,提及您正在使用 RIA 服务 很重要。我想你也在客户内部工作。这让事情完全与众不同。

在 RIA 服务中,确保返回初始加载时所需的整个实体图非常重要。您不想在实体上调用 .Load() 之类的东西,因为这对服务器来说是另一个热点,这对性能不利。例如,如果您在 Silverlight 客户端并从服务器请求实例列表,并且它们的相关属性尚未具体化,则为时已晚。此外,Include 不能在 Silverlight 客户端中工作。因此,RIA 服务具有服务器端工具,您可以使用它来确保您最初返回正确的、完全具体化的对象图。

您需要做的是在您的 RIA 服务服务器中使用 IncludeAttribute。您可以创建一个“伙伴”元数据类来使用 [Include] 来装饰您的实体模型。 the RIA Services overview document, section 4.8中有例子。

【讨论】:

你好,我不知道我们是否有相同的版本,但是在我编码时这两个选项都不可能。没有可用的“.Include”,只有“Intersect”..我使用以“ObjectContext”作为其基类的实体框架派生实体..当我进行项目时,智能感知中没有属性可供我设置.. Include 是 ObjectQuery 的方法,而不是 IQueryable。因此,请检查您拥有的参考类型。实体不是从 ObjectContext 派生的,它们是从 EntityObject 派生的。在我的示例中,投影对象上不会有任何 IntelliSense,因为我使用了 anonymous 类型。如果我使用了非匿名类型,就会有 IntelliSense。【参考方案3】:

使用.Include() 就像许多其他人所建议的那样是实现您需要的好方法。

但是,有时您可能需要稍后“重新加载”一些您没有“包含”的内容,或者您​​只是有时需要,因此在许多情况下放置 Include 语句可能会浪费计算周期。

如果是像“Product.Category”这样的单一关系(其中 Product.Category 是您从产品到类别的导航属性),您很可能还有一个“Product.CategoryReference”元素。您可以检查它是否已加载,如果没有,您可以“按需”加载它:

if(!Product.CategoryReference.IsLoaded)

    Product.CategoryReference.Load();

现在您引用的“类别”应该在内存中并且可以使用了。

如果您有一个导航属性引用了一组事物(例如,产品的“部件”),您可以直接在导航属性上执行相同的操作:

if(!Product.Parts.IsLoaded)

    Product.Parts.Load();

如果您没有将它们“包含”到您的 EF 查询中,这对于“按需加载”单个或集合类型导航属性可能是一种有用的技术。

马克

【讨论】:

谢谢大家,我意识到我无法实施许多提议的解决方案的原因是,一旦被 Silverlight 的域服务转换,上下文就不同了。在实体框架数据模型背后的代码中,我可以实现您的所有解决方案,而我刚刚发现了这一点。但多亏了你的帮助,我知道问题一定是我找错地方了……【参考方案4】:

您可以使用System.Data.Objects.ObjectQuery 的Include() 方法。此方法指定要包含在查询结果中的相关对象,并且对 Include() 的调用可以链接在一起以加载多个相关对象。

例如,要加载 ModifiedByUser 和 Category,您可以使用如下查询:

var q = from p in context.Products.Include("ModifiedByUser").Include("Category") 
        select p;

如果您的 Category 实体也有一个您想要加载的 ModifiedByUser 实体,您可以使用如下查询:

var q = from p in context.Products
              .Include("ModifiedByUser")
              .Include("Category.ModifiedByUser") 
        select p;

有关更多示例,请参阅 MSDN 上的 Shaping Query Results。

【讨论】:

我经常看到这个解决方案,所以我必须做一些与其他人完全不同的事情。基本上,我使用的是实体框架生成的数据模型中的上下文。我有最新的.Net。没有“包含”可用。你在这个例子中使用 dbml/linq 吗?我想这就是为什么它不同......

以上是关于Entity Framework 3.5 - 如何加载孩子的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework Core 实体关系的配置

Entity Framework Core 实体关系的配置

从哪里开始 .NET Entity Framework 和 ORM?

如何迁移 .NET Framework 应用程序? [3.5 到 2.0]

Windows 2008 R2 如何安装.net framework 3.5

Entity Framework 学习系列 - 认识理解Entity Framework