我有一个 MVC 4 项目,它使用 Code First 和 Entity Framework 6(由 SQL Server 2008 支持)。我正在尝试优化一个特别讨厌的查询,它看起来像:
var tops = Context.Top
.Include(t =>
t.Foo
.Select(f => f.FooChild1
.Select(c => c.Baz)))
.Include(t =>
t.Foo
.Select(f => f.FooChild3))
.Include(t =>
t.Foo
.Select(f => f.FooChild2))
.Include(t =>
t.Foo
.Select(f => f.FooChild1
.Select(c => c.Bar)))
.Where(t => t.Foo.Count > 0)
.ToList();
关系如下所示:
Top
1 ----> 0..N Foo
1 ----> 0..N FooChild1
1 ----> 0..N Bar
1 ----> 0..N Baz
1 ----> 0..N FooChild2
0..N ----> 1 FooChild3
如您所见,查询执行了大量的预加载,因此生成的查询有很多连接。事实证明,对于我对结果数据所做的事情,延迟加载太慢了。
为此生成的查询在我的 SQL Server 上执行大约需要 2 秒,但获取我需要的数据的手写查询只需要大约 91 毫秒。我能做些什么来改善这一点吗?
我试过的
Load()
我尝试通过调用我需要的所有其他表并删除所有Include
's来进行预加载。我不知道为什么(也许这个技巧不适用于DbContext
),但它没有效果。导航属性被延迟加载。
我在考虑什么
我想到的一个选择是手写一个 SQL 视图来查询我需要的数据,并在 Code First 中将一个实体映射到它。不知道如何准确地做到这一点,但我希望这样做可以避免生成的查询中的不良性能。
修改我的数据库的设计,以便将我需要的信息缓存在
Top
表中。我不喜欢这个选项中的数据重复,但至少我不必遍历这么多导航属性。
任何指针?