我被要求制作一份由相当复杂的 SQL 查询驱动的报告,该查询针对一个 SQL Server 数据库。由于报告所在的站点已经使用了 Entity Framework 4.1,所以我决定尝试使用 EF 和 LINQ 来编写查询:
var q = from r in ctx.Responses
.Where(x => ctx.Responses.Where(u => u.UserId == x.UserId).Count() >= VALID_RESPONSES)
.GroupBy(x => new { x.User.AwardCity, x.Category.Label, x.ResponseText })
orderby r.FirstOrDefault().User.AwardCity, r.FirstOrDefault().Category.Label, r.Count() descending
select new
{
City = r.FirstOrDefault().User.AwardCity,
Category = r.FirstOrDefault().Category.Label,
Response = r.FirstOrDefault().ResponseText,
Votes = r.Count()
};
这个查询统计选票,但仅限于提交了一定数量的最低要求票数的用户。
从性能角度来看,这种方法是完全失败的,因此我们转而使用ADO.NET,查询运行得非常快。我确实查看了使用SQL Profiler生成的LINQ SQL,尽管像往常一样看起来很糟糕,但我没有看到任何提示如何优化LINQ语句以使其更有效率。
以下是纯TSQL版本:
WITH ValidUsers(UserId)
AS
(
SELECT UserId
FROM Responses
GROUP BY UserId
HAVING COUNT(*) >= 103
)
SELECT d.AwardCity
, c.Label
, r.ResponseText
, COUNT(*) AS Votes
FROM ValidUsers u
JOIN Responses r ON r.UserId = u.UserId
JOIN Categories c ON r.CategoryId = c.CategoryId
JOIN Demographics d ON r.UserId = d.Id
GROUP BY d.AwardCity, c.Label, r.ResponseText
ORDER BY d.AwardCity, s.SectionName, COUNT(*) DESC
我想知道的是:这个查询太复杂了,EF和LINQ无法有效地处理它,还是我错过了什么技巧?
let response = r.First()
吗?或者交换Select和OrderBy的位置?就像这样https://dev59.com/aW445IYBdhLWcg3wJ298#5013740 - jessehouwingUser.Responses
这样的导航属性? - Gert Arnold