当我查询实体并向我的查询中添加许多包含数据时,非规范化
许多行包含的数据只有几列不同,而其他列包含相同的数据
在我开始使用ORM之前,我更喜欢编写几个查询并接收多个手工组装复杂对象的结果集。虽然最佳方法取决于架构,返回记录的数量和实体的复杂性。
我想知道EF是否支持实例化复杂实体的第二种方式以及如何打开此模式。
更新
为了更清楚,我会夸大一点。
假设我们有实体A
由100个简单属性组成:字符串,interges,日期等。除了这些属性外,实体还包含一大堆实体B
。
让我们考虑一下这个问题:
context.ASet.Include("CollectionOfB");
对于集合服务器中包含的每个项目B,返回A的简单属性的许多重复项。
如果没有ORM,我会创建查询,但只询问根对象的ID。然后我查询根对象,之后我查询引用根对象id的依赖项 然后我用字典和散列集处理MARS以组装实体。
答案 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太大,它与性能相比可能会产生相反的效果。
如果Root
和Child
之间的关系不多对多,您可以利用 Relationship Fixup 这是上下文(ObjectContext
或DbContext
)确保在实体加载到上下文或附加到上下文时自动构建对象图:
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
更好,而不是数据重复造成的性能损失。
优先选择其中一种替代方案是一个测试问题。我无法给出一般建议,使用适合所有情况的一个或另一个选项。