【发布时间】:2020-06-18 10:23:46
【问题描述】:
我有以下数据架构:
使用以下 LINQ 查询:
var profiles = (
from p in context.BusinessProfiles
join u in context.Users on p.UserId equals u.Id
join addr in context.BusinessAddress on p.ProfileId equals addr.ProfileId into addrj
from addr in addrj.DefaultIfEmpty()
join pa in context.BusinessProfileActivities on p.ProfileId equals pa.ProfileId into paj
from paIfNull in paj.DefaultIfEmpty()
where p.ProfileId >= 137 && p.ProfileId <= 139
group new { p, u, addr, paIfNull }
by new {
p.ProfileId,
p.CompanyName,
p.Email,
UserEmail = u.Email,
addr.City, addr.Region,
addr.Country,
ActivityProfileId = paIfNull.ProfileId }
into pg
select new {
pg.Key.ProfileId,
pg.Key.CompanyName,
Email = pg.Key.Email ?? pg.Key.UserEmail,
pg.Key.City,
pg.Key.Region,
pg.Key.Country,
MatchingActivities = pg.Key.ActivityProfileId > 0 ? pg.Count() : 0
} into result
orderby result.MatchingActivities descending
select result
);
结果:
这个结果是正确的(ProfileId137 有 0 个活动,138 有 1 个,139 有 2 个),但它会生成以下 SQL:
SELECT [b].[ProfileId], [b].[CompanyName], COALESCE([b].[Email], [a].[Email]) AS [Email], [b0].[City], [b0].[Region], [b0].[Country],
CASE WHEN [b1].[ProfileId] > CAST(0 AS bigint) THEN COUNT(*)
ELSE 0
END AS [MatchingActivities]
FROM [BusinessProfiles] AS [b]
INNER JOIN [AspNetUsers] AS [a] ON [b].[UserId] = [a].[Id]
LEFT JOIN [BusinessAddress] AS [b0] ON [b].[ProfileId] = [b0].[ProfileId]
LEFT JOIN [BusinessProfileActivities] AS [b1] ON [b].[ProfileId] = [b1].[ProfileId]
WHERE ([b].[ProfileId] >= CAST(137 AS bigint)) AND ([b].[ProfileId] <= CAST(139 AS bigint))
GROUP BY [b].[ProfileId], [b].[CompanyName], [b].[Email], [a].[Email], [b0].[City], [b0].[Region], [b0].[Country], [b1].[ProfileId]
ORDER BY CASE
WHEN [b1].[ProfileId] > CAST(0 AS bigint) THEN COUNT(*)
ELSE 0
END DESC
在 SQL 中,如果我像这样使用 COUNT([b1].[ProfileId]),我可以同时避免 CASE WHEN:
SELECT [b].[ProfileId], [b].[CompanyName], COALESCE([b].[Email], [a].[Email]) AS [Email], [b0].[City], [b0].[Region], [b0].[Country],
COUNT([b1].[ProfileId]) AS [MatchingActivities]
FROM [BusinessProfiles] AS [b]
INNER JOIN [AspNetUsers] AS [a] ON [b].[UserId] = [a].[Id]
LEFT JOIN [BusinessAddress] AS [b0] ON [b].[ProfileId] = [b0].[ProfileId]
LEFT JOIN [BusinessProfileActivities] AS [b1] ON [b].[ProfileId] = [b1].[ProfileId]
WHERE ([b].[ProfileId] >= CAST(137 AS bigint)) AND ([b].[ProfileId] <= CAST(139 AS bigint))
GROUP BY [b].[ProfileId], [b].[CompanyName], [b].[Email], [a].[Email], [b0].[City], [b0].[Region], [b0].[Country], [b1].[ProfileId]
ORDER BY [MatchingActivities] DESC
我的问题是,如何使用 LINQ 按分组 ActivityProfileId = paIfNull.ProfileId 计数并让 EF 生成上述 SQL?
我尝试了很多变体,主要导致 EF 到 SQL 错误。
MatchingActivities = pg.Count(t => t.ActivityProfileId!= 0)
MatchingActivities = pg.Select(t => t.paIfNull.ProfileId).Distinct().Count(),
MatchingActivities = pg.Count(t => t.paIfNull != null),
所有结果都会导致错误,例如System.InvalidOperationException: The LINQ expression ... could not be translated. 或将MatchingActivities 设为1 而不是0。
相关问答:
LINQ Count returning 1 instead of zero for an empty group
How to write left join, group by and average in c# entity framework Linq
【问题讨论】:
标签: sql-server linq entity-framework-6 sql-to-linq-conversion