1

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

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

更新

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

假设我们有A由 10000 个简单属性组成的实体:字符串、整数、日期等。除了这些属性 entity 还包含一个非常大的实体集合B

让我们考虑一下查询:

context.ASet.Include("CollectionOfB");

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

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

4

1 回答 1

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();

这适用于任何类型的关系,包括多对多关系。有 1 + N 个查询,如果 N 太大,与急切加载相比,它可能会在性能方面适得其反。

Root如果和之间关系Child不是多对多的,您可以利用关系修复,它是上下文 (或) 的一个功能,可确保在实体加载或附加到上下文时自动构建对象图: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方法很慢: https ://stackoverflow.com/a/8108643/270591 。但是,当您使用急切加载时,它仍然可能比数据重复造成的性能损失要好到一定数量。rootIdsrootIds

更喜欢其中一种选择是一个测试问题。我无法给出一般建议来使用适合所有情况的一种或另一种选择。

于 2012-12-29T12:52:15.003 回答