Linq延迟加载,(EF代码优先,Web.API和MVC)

时间:2013-05-23 04:00:39

标签: linq entity-framework

我遇到了一个奇怪的数据加载问题,我不明白,我希望有人可以向我解释发生了什么,以及如何更直接地完成我的任务。

我正在使用此问题主题中列出的技术构建网站。

我有一组对象 - 每个对象都有几个属性(名称,ID等)和其他对象的集合(ICollection<>)。所以只要查看对象树及其集合,它就像这样:

Tab
-TabRows
--Sections
---SectionRow
----Article

(因此每个选项卡都有一个或多个tabrow,每个tabrow有一个或多个部分,依此类推。每个子对象都有一个返回父对象的链接,因此每个sectionrow都有一个SectionID,每个Section都有一个TabRowID等等。)

好的,所以考虑到这个结构,请考虑以下代码:

// GET api/Tab/5
public Tab GetTab(int id)
{
    var tab = db.Tabs.FirstOrDefault(t => t.TabId == id);
    var tabrows = db.TabRows.ToList();
    var sections = db.Sections.ToList(); // This makes the tabRow.Sections populate
    var sectionrows = db.SectionRows.ToList();
    var articles = db.Articles.ToList();
    return tab;
}

所以这就是发生的事情。当第一行(var tab = ...)执行时,我得到一个tab对象,但是TabRows集合是空的。 (它不是null,因为构造函数实例化它)。

当第二行(var tabrows = ...)执行时,tab.TabRows突然填充。 tab.TabRows.Sections为空。

当第三行执行时,tab.TabRows.Sections会突然填充。

等等。

我假设这是代表Linq的某种“延迟加载”,或者也许是其他技术之一。但我不太了解他们。

有没有办法重新编写这个,这样我就可以调用第1行,基本上所有内容都自动填充,而不必单独引用每个集合中的每个对象?

1 个答案:

答案 0 :(得分:3)

默认启用延迟加载,禁用预先加载。实体框架允许您使用include语句提示急切加载。你的陈述会变成这样的。

 var tab = db.Tabs.FirstOrDefault(t => t.TabId == id).Include("TabRows");

或包含(t => t.TabRows);

请查看this link了解详情。

在您的情况下,您还需要处理嵌套包含。这意味着您最好选择另一个模型(您的类)结构如下

 Tabs -> Containing a List<TabRows> -> containing a List<Sections> etc. 

然后,您需要重新编写linq,以便使用嵌套包括填充整个模型,包括嵌套实体。

作为旁注,这些内部联接中的太多可能会减慢您的查询速度,因此在可能的情况下考虑数据库端的索引视图