在 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/