C# 基于条件和的EF核心组转换支持

C# 基于条件和的EF核心组转换支持,c#,entity-framework-core,entity-framework-core-2.1,C#,Entity Framework Core,Entity Framework Core 2.1,听到EF Core 2.1将支持分组翻译,我真的很兴奋。我下载了预览版并开始测试它,但发现在很多地方我仍然无法获得分组翻译 在下面的代码段中,TotalFlagCases查询将阻止group by translation工作。无论如何,我可以重写它,这样我就可以得到分组支持了吗?或者我可以采取的另一种方法 此表中有很多行,我不希望.NET必须加载所有这些行。我也使用行级数据,但一次只使用大约15条记录 var headerTask = (from c in cases group c b

听到EF Core 2.1将支持分组翻译,我真的很兴奋。我下载了预览版并开始测试它,但发现在很多地方我仍然无法获得分组翻译

在下面的代码段中,TotalFlagCases查询将阻止group by translation工作。无论如何,我可以重写它,这样我就可以得到分组支持了吗?或者我可以采取的另一种方法

此表中有很多行,我不希望.NET必须加载所有这些行。我也使用行级数据,但一次只使用大约15条记录

var headerTask = (from c in cases
    group c by 1
    into g
    select new CaseHeader
    {
        TotalCases = g.Count(),
        // ... A number of other aggregates
        TotalFlagCases = g.Where(a => a.Flag).Sum(b => 1),
    })
.DefaultIfEmpty(new CaseHeader()).FirstAsync();

在此版本的EF Core中,有一种方法可以进行条件求和。所提供的代码不会通过GROUPBY转换为所需的SQL,但将来的版本可能会支持这种方式。现在,您可以尝试以下方法:

var headerTask = cases
    .Select(c => new
    {
        c.Flag,
        c.YourKey,
        //other properties
    })
    .GroupBy(c => c.YourKey, (k, g) => new CaseHeader
    {
        TotalCases = g.Count(),
        // ... A number of other aggregates
        TotalFlagCases = g.Sum(b => a.Flag ? 1 : 0)
    });
当您将实体投影为匿名类型,然后将其分组,并在聚合函数中使用条件运算符时,它将转换为SQL,并使用group BY和聚合,如:

SELECT COUNT(*) AS [TotalCases], SUM(CASE
    WHEN [c].[Flag] = 1
    THEN 1 ELSE 0
END) AS [TotalFlagCases]
FROM [Cases] AS [c]
GROUP BY [c].[YourKey]

如果不将其投影为匿名类型,则当缺少上述Select函数时,它将不会转换为带有GROUP BY的SQL。看起来这个预发行版的查询翻译器不支持它,或者它是一个bug。

但是我发现我在很多地方仍然没有按翻译分组,不幸的是这是事实。尝试使用中间投影,得到无效的SQL异常。你所能做的就是在他们的问题跟踪器中发布/询问。但到目前为止的结论是,即使是2.1也不适合这种类型的查询。看,至少我很失望。我使用Linqkit和表达式,因为我有动态筛选和按逻辑分组。这段代码在C语言中看起来很优雅,但当我必须在存储过程中执行时,它就很难看了,而且很难优化,因为到处都有参数,我必须检查每个参数是否为null,因为我可能没有在特定的查询中实际使用它。我感觉如此接近!如果我能把条件求和或计数转换,那么我就可以避免这些丑陋的存储过程。我几乎不敢相信这是可行的!不过有点冗长。你能为我的特殊情况解决另一个问题吗?我不是在一个字段上分组,而是在整个数据集上分组,例如,从cases中选择count,而不是从cases GROUP BY SomeField中选择count。我似乎无法让它在那种情况下工作。我收到一个错误,说我的字段无法绑定。@jaromey在GroupBy中使用key,如b=>new{key=b.Id-b.Id}或b.Id*0等。您不能使用new{key=1},因为SQL Server在GroupBy中至少需要一列。这有点粗糙,但它可以工作。也许我可以找到一个更好的解决方案,或者将Key添加到匿名类型中,比如Key=c.Id*0,并通过b=>new{b.Key}在group中引用它。您也可以对key使用条件运算符,比如key=c。Flag?1:1幸运的是,当我这样做时,它会在本地计算linq表达式。不过,我会将您的答案标记为已接受的答案,因为它确实有效,除了我的edge案例。@jaromey我测试了它,它确实使用GROUP BY将其转换为SQL。你有没有像.GroupByc=>new{Key=c.Id*0},k,g=>newcaseheader。。。?注意:密钥是匿名类型