我有一个很大的LINQ查询,导致SQL查询效率低下。我非常确定我可以通过调整查询来优化它(如Scott Gu的this blog post和Eugene Prystupa的this excellent blog post中提到的那样,他们称之为"暗示&# 34。)
但是,此查询是重要的遗留代码,因此我宁愿不触及查询本身。是否可以通过修改生成的IQueryable来形成LINQ查询?
例如,我们假设低效查询位于GetOrders
,它将查询结果作为IQueryable<Order>
返回。我可以塑造IQueryable结果吗? E.g:
var result = GetOrders();
result = result.Select(o =>
new { o, o.Id, o.Customer, o.Payment })
.AsEnumerable()
.Select(o => o.o);
注意最后选择,即返回Order
个对象。 (有关此gem的信息,请参阅Prystupa's blog。)此示例整形的要点是让LINQ2SQL(或实体框架)将Customer表与Customer和Payment连接起来。查询订单后原始查询将查询这些表n
次,其中n
是订单数。
答案 0 :(得分:0)
通过实验,我发现这确实是可能的。只要查询仍然是LINQ-to-SQL或LINQ-to-Entities而不是LINQ-to-Objects,您仍然可以对查询进行整形。 (当您通过调用ToList
或AsEnumerable
之类的内容将结果集放入内存时,查询将变为LINQ-to-Objects。)
一个很大的警告:你只能在一对一的关系中获得SQL连接。如果在Select
的匿名对象中包含一对多或多对多子项,则生成的SQL仍将对子项的表进行n
个额外查询,其中n
1}}是记录的数量。这让我绊倒了很长时间,并让我觉得塑造根本不做任何事情。
我仍然希望能找到关于此事的官方文件。
答案 1 :(得分:-1)
我相信,正如博客文章所指出的,你必须做AsEnumerable
,否则中间选择将在查询中进行优化:
var result = GetOrders();
result = result.Select(o => new { o, o.Id, o.Customer, o.Payment })
.AsEnumerable()
.Select(o => o.o);