我正在使用实体框架来检索大型数据集。
数据集集有父/子关系,我需要在父母的同时带回子信息。
我发现EF最初发送一个查询以获取父对象列表,然后遍历每个父对象并向DB查询子信息。
因此,如果我有1000个父对象,我最终会对DB进行总共1001次调用(每个父对象一次,加上获取父项列表的原始查询)。
无论如何要进行EF查询这是一种更有效的方式吗?类似的东西:
SELECT * FROM CHILD_OBJECT_TABLE WHERE PARENTID IN (LIST OF PARENT_IDS HERE)
答案 0 :(得分:5)
您是如何执行查询的?如果您正在使用延迟加载,您将体验到您描述的行为。相反,使用Include
函数指定将特定导航属性(可以是相关实体或集合)作为查询的一部分加载。简而言之,EF将生成两种关系的扁平笛卡尔积,然后将数据正确地重新填充为父级>实例化对象时的子关系。
例如,如果您的父类有一个名为“Children”的集合属性,您可以这样称呼它:
context.Parents.Include("Children").Where(p=> ...)
或者如果您更喜欢查询语法到扩展方法语法......
from p in context.Parents.Include("Children")
where p ...
答案 1 :(得分:0)
以最简单的方式,您可以在一个上下文中使用两个调用,并且所有内容都将作为EF加载 无论如何都要映射关系,即使它们的加载方式不同,但是,所有的孩子都应该先加载,然后再加载父母。
// load children
var children = context.ChildTypes.Where(
x => x.Parent.SomeProperty == SomeValue );
var parents = context.ParentTypes.Where(
x => x.SomeProperty == SomeValue );
这将正确加载所有内容,并注意在两个查询中都应用了条件,不需要IN操作,因为EF将映射ParentType的条件以正确连接并加载相关条目。