在单独的查询中加载相关实体并对子集合进行排序

时间:2012-08-11 21:47:44

标签: entity-framework ef-code-first

我需要先使用EF 4.1 Code检索数据,这些数据包含在几个相关的表中。目前如果我使用这个

return Context.Set<Entity>()
              .Include(x => x.Children.Select(y => y.GrandChildren.Select(z => z.Child)))
              .Include(x => x.SomeEntity)
              .Include(x => x.AnotherEntity)
              .OrderByDescending(x => x.Id)
              .FirstOrDefault();

正确获取数据,但我担心两件事:

1)似乎没有办法对Chilren / GrandChildren进行排序

2)数据在一个表中展平,这意味着每个GrandChild记录都复制了Entity(和所有其他)数据

问题:

  • 我需要做些什么才能对Child / GrandChildren进行分类?
  • 在这种特殊情况下,第二点本身可能不是问题,因为传输的数据量不大 - 最多30条记录,包含30列。不过,我想知道是否有办法分别加载Enttity,Children和GrandChildren(3个查询),并将它们加入客户端站点?

返回的结果集需要是可更新的。

1 个答案:

答案 0 :(得分:3)

  

我需要做些什么才能对Child / GrandChildren进行分类?

在应用程序中对它们进行排序。这是唯一可靠的方式。 Include根本不允许排序,下面显示的方法不可靠,因为您无法控制EF的内部机制,并且您不能将导航属性设置为SortedList或其他集合维护排序顺序(即要求有可靠的排序关系)。

  

数据在一个表中展平,这意味着每个GrandChild记录都复制了Entity(和所有其他)数据

这是valid objection。您可以通过关闭延迟加载并使用单独的查询来加载数据来避免它:

context.Configuration.LazyLoadingEnabled = false;
var parent = context.Set<Entity>().First(e => e.Name = "ABC");
// Load relations in separate query
context.Set<Child>()
       .Where(c => c.Parent.Name == "ABC")
       .OrderBy(c => c.Name) // You can at least try it but as mentioned above it may not work in all scenarios
       .Load();
// Now parent.Children collection should be filled 

您可以对其他关系和嵌套关系采用相同的方法。关键是要为儿童和孙子女装载正确构建Where条件。

这并不意味着这种方法会比平坦的表更快。此方法为每个执行的查询分别进行数据库往返,因此在较小的数据集中,展平的表可以更快。