实体框架可以使用包含多个结果集吗?

时间:2012-12-27 17:53:12

标签: entity-framework

当我查询实体并向我的查询中添加许多包含数据时,非规范化 许多行包含的数据只有几列不同,而其他列包含相同的数据 在我开始使用ORM之前,我更喜欢编写几个查询并接收多个手工组装复杂对象的结果集。虽然最佳方法取决于架构,返回记录的数量和实体的复杂性。

我想知道EF是否支持实例化复杂实体的第二种方式以及如何打开此模式。

更新

为了更清楚,我会夸大一点。

假设我们有实体A由100个简单属性组成:字符串,interges,日期等。除了这些属性外,实体还包含一大堆实体B

让我们考虑一下这个问题:

context.ASet.Include("CollectionOfB");

对于集合服务器中包含的每个项目B,返回A的简单属性的许多重复项。

如果没有ORM,我会创建查询,但只询问根对象的ID。然后我查询根对象,之后我查询引用根对象id的依赖项 然后我用字典和散列集处理MARS以组装实体。

1 个答案:

答案 0 :(得分:2)

如果Root个实体的集合不是太大,您可以尝试显式加载(DbContext的语法):

var roots = context.Roots.Where(someCondition).ToList();
foreach (var root in roots)
    root.Children = context.Entry(root).Collection(r => r.Children)
        .Query().ToList();

这适用于任何类型的关系,包括多对多关系。有一个+ N个查询,如果N太大,它与性能相比可能会产生相反的效果。

如果RootChild之间的关系多对多,您可以利用 Relationship Fixup 这是上下文(ObjectContextDbContext)确保在实体加载到上下文或附加到上下文时自动构建对象图:

var roots = context.Roots.Where(someCondition).ToList();
var rootIds = roots.Select(r => r.Id);
context.Children.Where(c => rootIds.Contains(c.Root.Id)).Load();

(我假设Child有一个反向导航属性Root。)

无论加载了多少Root个实体,这些查询始终是两个查询。关系修复将自动为每个附加的root.Children填充root集合,以便结果看起来像,就像您已经使用了预先加载一样:

var roots = context.Roots.Include("Children").Where(someCondition).ToList();

不幸的是,如果Contains集合很大,rootIds方法很慢:https://stackoverflow.com/a/8108643/270591。但是,当你使用预先加载时,它仍然可能比一定数量的rootIds更好,而不是数据重复造成的性能损失。

优先选择其中一种替代方案是一个测试问题。我无法给出一般建议,使用适合所有情况的一个或另一个选项。