【问题标题】:EF LINQ Count by Grouped field按分组字段的 EF LINQ 计数
【发布时间】: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

Group by in LINQ

How to write left join, group by and average in c# entity framework Linq

【问题讨论】:

    标签: sql-server linq entity-framework-6 sql-to-linq-conversion


    【解决方案1】:

    简而言之,你不能! EF Core 仍然不支持。

    看到这个: https://github.com/dotnet/efcore/issues/17376

    另见: https://stackoverflow.com/a/61878332/9212040

    【讨论】:

      猜你喜欢
      • 2016-06-18
      • 1970-01-01
      • 2010-09-27
      • 2015-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多