首页 文章

EF核心组通过延迟执行和SQL端分组

提问于
浏览
2

使用EF Core 2.1,它支持Group By转换但不是在我投影键值之后 .

我有一个查询需要允许一系列分组类型和一系列聚合类型 .

分组依据:年,年/月,年/月/日等

聚合方式:平均,总和,最小,最大等

我创建了两个 switch 语句,一个用于分组,另一个用于聚合 . 我的问题是我无法推迟执行并在SQL中执行分组 . 如果不是,结果数据集非常大 .

这是一种合理的方法还是我应该使用原始查询?

这是推迟并按需要分组,但密钥类型对于年/月是唯一的,如果我想按年份/月/日等不同的分组,我无法为第二个 switch 中的聚合提供一般解决方案 .

var query1 = series
     .GroupBy(k => new { k.Created.Year, k.Created.Month, });

var result1 = query1
    .Select(i => new { i.Key, Value = i.Average(a => a.DataValue) });

只要将密钥转换为字符串,就会在客户端进行分组:

var query2 = series
      .GroupBy(k => k.Created.Year.ToString());

var result2 = query2
    .Select(i => new { i.Key, Value = i.Average(a => a.DataValue) });

这也会导致分组发生在客户端:

var query3 = series
     .GroupBy(k => new { k.Created.Year, k.Created.Month, })
     .Select(i => new
     {
         Key = $"{i.Key.Year}-{i.Key.Month}",
         Values = i.ToList()
     });

任何想法如何完成我的查询?理想情况下,我需要一个组服务器端的公共组密钥或基于查询中的函数传递聚合的方法 . 生成基于 string 的密钥似乎可以确保分组发生在客户端 .

1 回答

  • 3

    我能够在EF Core 2.1(和2.2)中获得SQL转换的唯一方法是按条件分组复合匿名类型,包括所需的数据部分:

    bool includeYear = ...;
    bool includeMonth = ...;
    bool includeDay = ...;
    bool includeHour = ...;
    
    var query1 = series
        .GroupBy(e => new
        {
            Year = includeYear ? e.CreatedDate.Year : 0,
            Month = includeMonth ? e.CreatedDate.Month : 0,
            Day = includeDay ? e.CreatedDate.Day : 0,
            Hour = includeHour ? e.CreatedDate.Hour : 0
        });
    

    奇怪的是,如果我为组密钥创建一个特殊类,其具有与匿名类型完全相同的属性并将 new { ... } 更改为 new MyKeyType { ... } ,则EF Core将切换到客户端评估 .

    不久, GroupBy (而且不仅仅)SQL翻译仍然不稳定 . 看起来我们必须等待3.0才能最终获得该领域的改进 .

相关问题