在Entity Framework 4中,默认禁用延迟加载功能。

62

看起来EF4默认启用了延迟加载。至少在我的项目中,我可以看到

dataContext.ContextOptions.LazyLoadingEnabled

默认情况下是true。我不想使用延迟加载,也不想写:

dataContext.ContextOptions.LazyLoadingEnabled = false;

每次我得到一个新的上下文时,都会出现这个问题。因此,是否有一种方法可以默认关闭它,比如在整个项目中?

5个回答

68

以下答案是针对 Database-FirstModel-First 工作流程(在提问时,这两种工作流程是 Entity Framework(版本 <= 4.0)唯一可用的两种工作流程)。如果您正在使用 Code-First 工作流程(自 EF 版本 >= 4.1 起可用),请参阅 ssmith 的 answer 以获取正确的解决方案。


在edmx文件的<ConceptualModel><EntityContainer>定义中,有一个用于延迟加载的属性,您可以将其通常设置为false:
<EntityContainer Name="MyEntitiesContext" annotation:LazyLoadingEnabled="false">

在ObjectContext构造函数中,将创建以下设置:
public MyEntitiesContext() : base("name=MyEntitiesContext", "MyEntitiesContext")
{
    this.ContextOptions.LazyLoadingEnabled = false;
    OnContextCreated();
}

我的例子并不是说生成的 ObjectContext(或新版 EF 中的 DbContext)应该手动编辑(这会被每次从数据库更新模型时覆盖,正如 ctorx 所指出的那样),而是在 EDMX 文件的 edmx:ConceptualModels 部分的 EntityContainer 元素中添加 annotation:LazyLoadingEnabled="false" 属性进行编辑 - 可以在 XML 编辑器中手动添加,也可以在设计器表面的属性页面上使用此选项,右键单击 EDMX 然后选择 Properties。

enter image description here

这个EDMX文件的修改会自动在构造函数中生成禁用延迟加载选项的上下文类,如上所示。当从数据库更新模型时,EDMX文件本身不会被覆盖。

16
这需要你修改生成的代码,如果你修改了模型,它将被覆盖。考虑使用一个ObjectContextFactory并在工厂中进行更改。这样你只需要设置一次选项,而不会改变自动生成的代码。 - ctorx
@ctorx - 我认为比工厂更简单的选择是实现部分OnContextCreated以关闭延迟加载?还是我漏掉了什么? - James Manning
工厂还可以用于允许显式提供连接字符串,通过依赖注入按需或有条件地提供。在我看来,这种增加的抽象化正当其所,即使从技术上讲,它并不是必要的。 - ctorx
@ctorx:两年多过去了,即使我点赞了你的评论,因为我认为你的批评是完全正确的,现在我再次理解了我的答案,实际上根本不需要修改生成的代码 :) 请参见我的答案底部的编辑部分。 - Slauma
1
我再次将您的答案标记为已接受,以尝试消除任何困惑(或者可能会产生更多困惑!)。 - Mike Chamberlain

64
我写了一个快速示例,展示了如何使用EF Code First的新惰性加载功能。在Code First模型中实现您想要的内容只需要在您的DbContext构造函数中添加一行代码,如下所示:
public BlogContext()
{
    this.Configuration.LazyLoadingEnabled = false;
}

11
这段代码中,: base()this. 都是多余的,虽然它们并不重要。 - Ben Lesh
就功能而言,是的,但从可读性角度来看,我认为有时包括“this”是有用的。不过关于“base()”,我同意,我想不出添加它的理由。 - Jeff Bobish
是的,不确定为什么base()曾经在其中。已删除。 - ssmith
base() 用于指定要使用的连接字符串,对吧?如果您没有指定连接字符串,那么它不是多余的吗? - cr1pto

24

如果你正在使用EF4 Code First,那么在你的上下文初始化时,有一个"OnModelCreated"的重写方法。

在这个方法中,我只是调用了并设置了属性,然后问题就解决了。

protected override void OnModelCreating(DbModelBuilder modelBuilder) {
     base.Configuration.LazyLoadingEnabled = false;
}

我的模型现在更易使用了。懒加载很好...但是当你不想要它时就不适用了。而且当你开始出现循环引用时,这就太荒谬了。


4
这样做行不通,因为它只会禁用构建模型的上下文实例(通常是应用程序启动后第一个使用的实例)的惰性加载。对于所有后续的上下文实例,OnModelCreating 方法都不会被调用,LazyLoadingEnabled 属性将具有默认值 - 即 true - Slauma
@Slauma - 今天我遇到了完全相同的问题,因此我已经编辑了这个答案(因为它是被接受的答案),将其更改为在构造函数中设置。如果我有权将被接受的答案从这个更改为你的答案,我会这样做。 :) - James Manning
1
@JamesManning:这个问题的历史很奇怪。几个月前我的答案被接受了,但我的答案并不好(ctorx的评论是非常有道理的)。然后问题的所有者将接受移到了这个错误的答案上,直到你的编辑之前。此外,这是一个针对DbContext的答案,而这个问题提问时ObjectContext还没有出现。问题中的代码片段仍然是针对ObjectContext的。现在你已经将其编辑成了一个正确的DbContext答案,但它与ssmith的答案是一样的,而且比他的答案还要早一年。但两者都不是ObjectContext的答案。相当疯狂 :) - Slauma
@Slauma - 确实很疯狂!如果您的答案只是由于ctor重新生成而“偏离”,那么在MyEntitiesContext的partial class中的“partial void OnContextCreated()”方法中将其编辑为LazyLoadingEnabled = false是否是“正确”的修复/更改?对此感到抱歉 - 我可能应该什么都不做。 :) - James Manning
@JamesManning:是的,听起来不错。如果你用那个想法写一个自己的答案,那将是最好的,也可能会被接受 :) 你也可以编辑我的答案...随你喜欢。 - Slauma
@JamesManning:我决定撤销你对原回答的编辑。在另一个上下文中,我浏览了一下meta,看看有什么共识,似乎意思是除了回答的所有者本人之外,不应该改变回答的含义(例如:http://meta.stackexchange.com/a/107512/174063 + 那里的其他答案)。在你的编辑之后,评论已经变得难以理解了。这里的所有其他答案都是正确的,所以对于某人来找到解决方案不应该很困难。如果我们确信一个答案是错误的,我们应该用评论和/或负评来指出它。 - Slauma

23

你还可以从设计器中进行操作。只需打开.edmx文件,右键单击模型中的任意位置并选择“属性”。然后将LazyLoadingEnabled设置为false。 在此输入图片描述


4
如果您正在使用代码优先进行建模,只需删除引用/对象属性上的virtual关键字即可。在引用上使用虚拟关键字将启用该特定引用上的LazyLoading。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接