从 Linq GroupJoin 生成的 SQL 忽略所有条件

问题描述 投票:0回答:1

我正在尝试使用 LINQ to SQL 查询语法查询一天中每小时打开的票证数量。我得到了正确的结果,但是生成的 SQL 与我预期的有很大不同。

我在 LinqPad 上的查询是:

int[] hours = Enumerable.Range(0, 24).ToArray();
DateTime Nov = new DateTime(2023, 11, 14);
var q = (
            from h in hours
            join t in Tickets on h equals t.CreatedAt.Hour into ht
            from lht in ht.Where(tk => (tk.CreatedAt.Date == Nov.Date) && (tk.OrganizationId == 1) && (!tk.IsDeleted) ).DefaultIfEmpty()
            group lht by h into ftable
            select new {id = ftable.Key, count  = ftable.Count(f => f != null)}
        ).Dump();

由于某种原因,生成的 SQL 查询是整个门票表的简单选择:

SELECT `t`.`Id`, `t`.`ClosedAt`, `t`.`CreatedAt`, `t`.`CreatedBy`, `t`.`isDeleted`, `t`.`LastUpdatedAt`, `t`.`LastUpdatedBy`, `t`.`LinkedSessionId`, `t`.`OrganizationId`, `t`.`Priority`, `t`.`PropertyId`, `t`.`PublicId`, `t`.`RecipientId`, `t`.`Source`, `t`.`Status`, `t`.`Subject`, `t`.`TicketId`
FROM `tickets` AS `t`

我不确定这里发生了什么,但看起来

join t in Tickets on h equals t.CreatedAt.Hour into ht
行只是简单地获取整个表,然后在内存中进行其余的分组和where条件,这是非常低效的。

是否有人遇到过类似的事情或者可以解释这种行为,以及如何强制它在生成的 sql 中生成带有 WHERE 和 GROUP BY 子句的正常 LEFT JOIN。

linq entity-framework-core linq-to-sql ef-core-7.0
1个回答
0
投票

如果您从本地集合开始查询,则意味着您将使用

Enumerable
扩展,这意味着将整个表加载到内存中并且不会应用任何过滤器。 我建议对服务器上的现有数据进行分组,然后通过错过的时间来丰富数据:

DateTime Nov = new DateTime(2023, 11, 14);
var startDate = Nov;
var endDate = startDate.AddDays(1);

var query =
    from t in Tickets
    where t.CreatedAt >= startDate && t.CreatedAt < endDate
    group t by t.CreatedAt.Hour into g
    select new 
    {
        id = g.Key, 
        count = g.Count()
    };

int[] hours = Enumerable.Range(0, 24).ToArray();

var enriched = 
    from h in hours
    join d in query on h equals d.id into gj
    from d in gj.DefaultIfEmpty()
    select new
    {
        id = h,
        count = d == null ? 0 : d.count
    };

enriched.Dump();
© www.soinside.com 2019 - 2024. All rights reserved.