只需尝试F#3.0,就多列分组而言,只需要花一点时间.显而易见的是
query {
for d in context.table do
groupBy (d.col1,d.col2) into g
select (g.Key)
}
Run Code Online (Sandbox Code Playgroud)
但是我得到了"LINQ to Entities中只支持无参数构造函数和初始值设定项".例外.
我似乎无法在msdn上找到一个例子
http://msdn.microsoft.com/en-us/library/hh225374(v=vs.110).aspx
http://msdn.microsoft.com/en-us/library/hh361035(v=vs.110).aspx
而且我意识到我的问题类似于" F#中的实体框架和匿名类型 ",但它似乎是专注于powerpack/F#2.x而且我希望F#3.0有一个优雅的答案......任何想法?
更新:
我在阅读Brian的帖子时遇到了CLIMutable属性:
http://blogs.msdn.com/b/fsharpteam/archive/2012/07/19/more-about-fsharp-3.0-language-features.aspx
我很乐观,所以我试过了
[<CLIMutable>]
type MyRecord = { Column1 : int; Column2 : int }
query {
for d in context.table do
groupBy {Column1 = col1; Column2 = col2} into g
select (g.Key)
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,我得到完全相同的例外.
以下是在 c# 中用于分组并转换为 f# 的多列示例(过于偏执的管理使我重命名了所有内容,但我相信我一直保持一致):
(数据库由SqlMetal生成,GetSummedValuesResult是F#记录类型)
C#
public static class Reports
{
public static IReadOnlyList<GetSummedValuesResult> GetSummedValues(TheDatabase db, DateTime startDate, DateTime? endDate)
{
var query =
from sv in db.SomeValues
where (sv.ADate >= startDate && sv.ADate <= (endDate ?? startDate))
group sv by new { sv.ADate, sv.Owner.Name } into grouping
select new GetSummedValuesResult(
grouping.Key.ADate,
grouping.Key.Name,
grouping.Sum(g => g.Value)
);
return query.ToList();
}
}
Run Code Online (Sandbox Code Playgroud)
F#
type Reports() =
static member GetSummedValues (db:TheDatabase) startDate (endDate:Nullable<DateTime>) =
let endDate = if endDate.HasValue then endDate.Value else startDate
let q = query {
for sv in db.SomeValues do
where (sv.ADate >= startDate && sv.ADate <= endDate)
let key = AnonymousObject<_,_>(sv.ADate, sv.Owner.Name)
groupValBy sv key into grouping
select {
ADate = grouping.Key.Item1;
AName = grouping.Key.Item2;
SummedValues = grouping.Sum (fun (g:TheDatabaseSchema.SomeValues) -> g.Value)
}
}
List(q) :> IReadOnlyList<GetSummedValuesResult>
Run Code Online (Sandbox Code Playgroud)
所以要使用的是Microsoft.FSharp.Linq.RuntimeHelpers.AnonymousObject
请注意,您不应该将 Seq 模块用于聚合函数!
SummedValues = grouping |> Seq.sumBy (fun g -> g.SomeValues)
Run Code Online (Sandbox Code Playgroud)
虽然这可行,但它在客户端进行聚合,而不是制定适当的 SQL。