linq - Entity Framework 核心 GroupBy 日期

标签 linq f# entity-framework-core

在 C# 中,您可以按 .Date 分组:

db.History.GroupBy(x => x.Timestamp.Date)
          .Select(g => new { key = g.Key, aggregate = g.Count() })

但是,等效的 F# 不起作用:

db.History.GroupBy(fun x -> x.Timestamp.Date)
          .Select(fun g -> { Date = g.Key; Count = g.Count()} )

相关记录:

type DateCount = {
    Date: DateTime
    Count: int
}

它抛出以下错误:

System.InvalidOperationException: The LINQ expression 'DbSet<HistoryEntity> .GroupBy( source: h => copyOfStruct => copyOfStruct.Date.Invoke(h.Timestamp), keySelector: h => h)' could not be translated. 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().

如何按日期分组?

最佳答案

所以在 C# 中,当您使用 LINQ-to-SQL 查询 时,您正在使用 IQueryable<T> 上的扩展方法。 .如果我们看一下 say 的签名,GroupBy method ,你会看到函数签名实际上是

IQueryable<TSource>.GroupBy<TSource,TKey>(Expression<Func<TSource,TKey>> keySelector)

这是怎么回事? Expression<>是一种特殊类型 - 当 C# 编译器发现 Expression<> 时类型,编译器构建一个 AST,并传递 AST 对象(类型为 Expression<Func<>> ),而不是通常的委托(delegate)。预计底层函数将检查 AST 并构建最终需要的任何查询表达式,例如用于查询数据库的 SQL。

你可以自己试试:

Expression<Func<int>> getRandom = () => 4; //random, chosen by fair dice roll

您可以检查 getRandom 的属性看AST。 由于魔术发生在 C# 编译器中,因此当您在 F# 中执行此操作时,这不会削减它。

更详细地说,F# 编译器可以识别 Expression<> ,但它通过应用隐式 F# 引号来实现 - 因此您将获得一个 F# 引号包装的方法调用,该方法调用转换为 C# 表达式树。 (很抱歉,如果它继续运行。)

F# 有自己的查询理解 builder for SQL .它可以让你写出类似seq的计算表达式。转换为 SQL 查询。这就像您期望的那样工作。

query {
    for record in db do
    select record
}

关于linq - Entity Framework 核心 GroupBy 日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60005578/

相关文章:

c# - 流利的查询表达式——两者之间有什么优势吗?

f# - MongoDB自定义序列化程序实现

f# - 尝试使用连续传递样式来避免使用 minimax 算法的堆栈溢出

c# - XUnit 测试 DbContext 没有处理

c# - 如何将 Enum int 值传递给 Controller

c# - 将一个字典转换为另一个具有不同键类型的字典

c# - 我可以从 Func<T, object> 获取特定的元数据吗?

winforms - 构建一个可取消的非阻塞后台 worker

asp.net-core - .NET Core 1.0 和 EntityFramework 7 不兼容

entity-framework - 如何使用 EF Core 加载导航属性?