【问题标题】:EF Core 3.1 unexpected SQL generation when combine join and group byEF Core 3.1 组合连接和分组时意外 SQL 生成
【发布时间】:2021-07-28 09:03:17
【问题描述】:

我有这段执行 SQL 左连接操作的 C# 代码(使用 EF Core 3.1)。

var groupedQuery = query.GroupBy(x => x.CreatedTime.Date)
    .Select(o => new
    {
        Date = o.Key,
        Count = o.Count()
    });

var acceptedGroupedQuery = query.Where(o => o.Accepted).GroupBy(x => x.CreatedTime.Date)
    .Select(o => new
    {
        Date = o.Key,
        Count = o.Count()
    });

var projectedQuery = groupedQuery.GroupJoin(acceptedGroupedQuery, o => o.Date, i => i.Date,
        (o, i) => new { Total = o, Accepted = i })
    .SelectMany(o => o.Accepted.DefaultIfEmpty(), (joined, accepted) => new 
    {
        Date = joined.Total.Date,
        Total = joined.Total.Count,
        Accepted = accepted.Count
    });

var result = await projectedQuery
    .Skip(model.Skip).Take(model.Take).ToArrayAsync(cancellationToken: cancellationToken);

对应的SQL生成是

exec sp_executesql N'SELECT [t].[c] AS [Date], CAST([t].[c0] AS float) AS [Total], CAST([t0].[c0] AS float) AS [Accepted]
FROM (
    SELECT CONVERT(date, [p].[CreatedTime]) AS [c], COUNT(*) AS [c0]
    FROM [PartnerInvitation] AS [p]
    WHERE [p].[DeletedTime] IS NULL
    GROUP BY CONVERT(date, [p].[CreatedTime])
) AS [t]
LEFT JOIN (
    SELECT CONVERT(date, [p0].[CreatedTime]) AS [c], [t].[c0]
    FROM [PartnerInvitation] AS [p0]
    WHERE [p0].[Accepted] = 1 
    GROUP BY CONVERT(date, [p0].[CreatedTime])
) AS [t0] ON [t].[c] = [t0].[c]
ORDER BY (SELECT 1)
OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY',N'@__p_0 int,@__p_1 int',@__p_0=0,@__p_1=10

上述查询给出以下错误:

消息 4104,级别 16,状态 1,第 9 行。无法绑定多部分标识符“t.c0”。

我希望左连接中的第二个选择语句是 SELECT ..., COUNT(*) as [c0] 而不是 SELECT ..., t.[c0]

知道这里发生了什么以及如何解决吗?

【问题讨论】:

  • 看来是个bug
  • 我在此处的 EF Core 存储库中发布了一个问题:#24847
  • @TrầnNamTrung 因为它已经修复(见我的回答),他们应该知道它,所以发布一个新问题无济于事 - 很可能它会作为重复的东西被关闭。

标签: c# sql-server entity-framework-core ef-core-3.1


【解决方案1】:

知道这里发生了什么

显然是 EF Core 3.x 错误 - 在 EF Core 5.x 中,相同的查询得到预期的正确翻译。

如何解决?

修复库错误基本上是不可能的。好的是它是固定的,坏的是它在 v5.x 中而不是在 v3.1 中修复 - 它出现在最新的 v3.1.14 中,因为他们已经在 v6.0 上工作,我认为它永远不会在 v3.1 中得到修复。

所以一种选择是升级到最新的 v5.x。

另一种选择,但仅针对此特定查询是以不使用连接的方式重写它 - 它的作用可以通过单个 GroupBy 查询和条件轻松更有效地实现Sum(在 v5.x 中你也可以使用条件 Count),例如摆脱 groupedQueryacceptedGroupedQuery 就可以了

var projectedQuery = query
    .GroupBy(e => e.CreatedTime.Date)
    .Select(g => new
    {
        Date = g.Key,
        Total = g.Count(),
        Accepted = g.Sum(e => e.Accepted ? 1 : 0)
    });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-18
    • 2014-11-19
    • 2014-03-21
    • 2014-09-23
    • 1970-01-01
    相关资源
    最近更新 更多