如何优化此Linq查询以删除不必要的SELECT Count(*)

4

我有三张表,分别为Entity、Period和Result。Entity和Period之间是一对一的映射关系,而Period和Result之间是一对多的映射关系。

这是linq查询:

int id = 100;
DateTime start = DateTime.Now;

from p in db.Periods
where p.Entity.ObjectId == id && p.Start == start
select new { Period = p, Results = p.Results })

这是生成的SQL语句的相关部分:
SELECT [t0].[EntityId], [t2].[PeriodId], [t2].[Value], (
    SELECT COUNT(*)
    FROM [dbo].[Result] AS [t3]
    WHERE [t3].[PeriodId] = [t0].[Id]
    ) AS [value2]

FROM [dbo].[Period] AS [t0]
INNER JOIN [dbo].[Entity] AS [t1] ON [t1].[Id] = [t0].[EntityId]
LEFT OUTER JOIN [dbo].[Result] AS [t2] ON [t2].[PeriodId] = [t0].[Id]
WHERE ([t1].[ObjectId] = 100) AND ([t0].[Start] = '2010-02-01 00:00:00')

SELECT Count(*)的来源在哪里,我该如何去掉它?我不需要每个“Period”的“Results”计数,这会使查询速度慢上一个数量级。

SELECT Count(*)是用来统计结果数量的函数,在这个查询中可能是用于分组或者筛选数据。如果你不需要这个统计结果,可以将其从查询中删除。


2
我认为这个计数器实际上是将笛卡尔积结果转换为1对多结果的方法。因此,如果您有许多期间具有许多结果,则在转换结果时它知道每个期间应该具有的结果数量。 - Phill
1
我猜这种行为的原因是LinqToSql试图出于某些原因准备嵌套集合的许多行。尝试使用数据上下文的DeferredLoadingEnabled属性或任何其他关于延迟加载的属性进行调整。无论如何,现在不支持LinqToSql。请转换到EF。 - Genius
5
“LinqToSql现在不支持了吗?”它在最新的.NET 4.0版本中,仍然受支持。也许你不支持它,但那是另一回事!:-P - Kirk Broadhurst
就像@Phill所说的那样,它需要知道每个实体在子集合“Results”中放置的行数。 - Magnus
1
@dan 最近在我的当前项目中我们一直在这样做,特别是在长查询上。我们发现LINQ-to-SQL每次只能检索一个子集合,所以如果你想要2、3或更多的子对象,它将进行多个数据库调用。对于我们来说,通过创建存储过程从单个、更复杂的查询中创建对象要快得多。虽然有点麻烦,但确实有效。 - Kirk Broadhurst
显示剩余2条评论
1个回答

1

考虑使用Context.LoadOptions并指定Period to LoadWith(p=>p.Results)来急切地加载具有结果的期间,而无需投射到匿名类型中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接