在 LINQ GroupBy 中使用方法

Use method inside LINQ GroupBy

我正在尝试操作要在字典中使用的 GroupBy 子句中的属性:

var lifeStages = await _dbContext.Customers
                                 .GroupBy(x => GetLifeStage(x.DoB))
                                 .Select(x => new { LifeStage = x.Key, Count = x.Count() })
                                 .ToDictionaryAsync(x => x.LifeStage, x => x.Count);

我期待这样的结果

青少年:10, 成人:15岁, 高级:12 等等

但是出现错误:

Either rewrite the query in a form that can be translated,
    or switch to client evaluation explicitly 
    by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). 

当然我不能将 ToDictionary() 与任何提到的调用结合起来,拆分查询并没有解决问题或教我任何东西)

我试过将 GetLifeStage() 设为静态和异步,两者也没有区别。该方法被调用,执行它需要做的事情,但仍然无法翻译 GroupBy

如果我省略 Select() 部分并使用 GroupBy 的键,同样的错误: “...无法翻译。”

我也看到一个错误,说我在试用期间无法将 GroupBy() 与 ToDictionary() 结合使用,但似乎没有弹出 atm。

由于我运行没有想法,欢迎大家提出建议!

更新:

private LifeStage GetLifeStage(DateTimeOffset doB)
{
  var ageInMonths = Math.Abs(12 * (doB.Year - DateTimeOffset.UtcNow.Year) + doB.Month - DateTimeOffset.UtcNow.Month);

  switch (ageInMonths)
  {
    case < 216:
      return LifeStage.Adolescent;
    case < 780:
      return LifeStage.Adult;
    case >= 780:
      return LifeStage.Senior;
  }
}

问题是 custom GetLifeStage 方法在 GroupBy expression 中的使用。自定义方法无法转换为 SQL,因为查询转换代码无法知道该方法中的内容。而且不能调用,因为翻译过程中根本没有对象

为了使其可翻译,您必须用它的主体替换自定义方法调用,转换为可翻译的表达式——基本上可以用作表达式主体方法的东西。您不能使用变量和开关,但可以使用条件运算符。您可以使用中间投影 (Select).

而不是变量

这是等效的可翻译查询:

var lifeStages = await _dbContext.Customers
    .Select(c => new { Customer = c, AgeInMonths = Math.Abs(12 * (c.DoB.Year - DateTimeOffset.UtcNow.Year) + c.DoB.Month - DateTimeOffset.UtcNow.Month) })
    .GroupBy(x => x.AgeInMonths < 216 ? LifeStage.Adolescent : x.AgeInMonths < 780 ? LifeStage.Adult : LifeStage.Senior)
    // the rest is the same as original
    .Select(x => new { LifeStage = x.Key, Count = x.Count() })
    .ToDictionaryAsync(x => x.LifeStage, x => x.Count);