Entity Framework 4 选择性延迟加载属性

27

是否可以加载实体并排除某些属性?其中一个属性的选择成本很高。我想延迟加载该属性。这可能吗?

4个回答

38

现在您已经阅读了每个人的回复,我会给您正确的答案。EF不支持属性的惰性加载。然而,它支持比这更强大的概念。它被称为表拆分,您可以将一个表映射到两个实体。例如,数据库中的产品表可以映射到产品实体和ProductDetail实体。然后,您可以将昂贵的字段移动到ProductDetail实体,然后在产品和ProductDetail实体之间创建一个1..1关联。然后,只有当您需要时才能惰性加载productdetail关联。

在我的书的性能章节中,我有一个名为13-9. 将昂贵的属性移动到另一个实体 的配方。

希望能对您有所帮助!

Julie Lerman有一篇文章介绍了如何拆分表格


3
谢谢。我必须这么做。但是EF4应该支持标量属性的延迟加载,这会非常方便。 - user342552
我知道团队正在努力支持下一个版本的开箱即用延迟加载属性,但我认为将昂贵的列移动到另一个实体可以打开同时延迟加载几个昂贵属性的机会。想象一下,你有一个Employee对象,其中包含EmployeePicture和employeedescription两个昂贵的属性,你想要延迟加载它们两个,但是每当你想要加载它们时,你都希望同时加载它们。这是在linq to sql中做不到的事情。 - zeeshanhirani
是的,如果有多个昂贵的字段,那么 EF 团队可以启用一个类似于 LoadAllLazyProperties 的标志,允许 EF 加载所有标记为 Lazy Load 的标量属性,无论何时请求其中任何一个。这将改善像您提到的这种情况,而不需要分离 EntityTypes! - user342552

7

使用标量属性,选择性地不加载某个属性的唯一方法是在ESQL或L2E中进行投影:

var q = from p in Context.People
        select new
        {
            Id = p.Id,
            Name = p.Name // note no Biography
        };

+1 给 Dan;懒加载比预加载更糟,如果你想要控制加载,请明确指出。


感谢您的建议。是的,但这种投影并不高效。首先,它会导致一个无法直接用作People的匿名类型。必须创建和正确实例化一个新的People对象,这将浪费在对象之间解析的时间。此类型也无法被上下文跟踪。 - user342552
2
@Nazaf,你过早地进行了优化。 - Craig Stuntz

1

假设您在EntityFramework DbSet上执行一个查询,其中目标实体包含一个BigProperty和一个SmallProperty, 您尝试仅访问SmallProperty而不在内存中加载BigProperty时:

//this query loads the entire entity returned by FirstOrDefault() in memory
//the execution is deferred during Where; the execution happens at FirstOrDefault
db.BigEntities.Where(filter).FirstOrDefault()?.SmallProperty;

//this query only loads the SmallProperty in memory
//the execution is still deferred during Select; the execution happens at FirstOrDefault
//a subset of properties can be selected from the entity, and only those will be loaded in memory
db.BigEntities.Where(filter).Select(e=>e.SmallProperty).FirstOrDefault();

因此,您可以利用这种行为仅查询您实际需要的BigProperty,并使用select语句在其他地方明确过滤它。 我使用Visual Studio调试诊断工具的内存使用功能对此进行了测试。

1

stimms 是正确的,但在使用延迟加载时要小心。您可能会遇到性能问题,并且不会意识到属性正在在代码的特定位置加载数据。这是因为它在使用属性时加载数据。

我更喜欢使用显式加载。这样,您就知道何时以及在哪里加载它们。这里有一个链接,提供了 LoadProperty 的示例 http://sankarsan.wordpress.com/2010/05/09/ado-net-entity-framework-data-loading-part-2/

您还可以使用 Include 方法来使用急切加载。这里有一个示例:http://wildermuth.com/2008/12/28/Caution_when_Eager_Loading_in_the_Entity_Framework


Stimms和Dan, 我不是指相关属性,而是指像传记这样的字段(类成员),它在加载实体时非常昂贵,我希望在必要时才进行延迟加载。据我所知,这在EF4中不起作用。有没有办法做到这一点? - user342552
1
所以你想要延迟加载一个标量属性?我可能会尝试将传记拆分为它自己的实体,然后将其设置为导航属性。然后我就可以进行延迟/急切/显式加载了。可能有更好的方法...我有机会时会测试这个理论。 - Dan H
谢谢,这似乎是唯一有效的方法。 - user342552

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