LINQ不会使用EF Core

时间:2018-08-24 15:19:38

标签: c# entity-framework-core

我有一个ASP.NET Core应用程序,可通过EF Core在SQL Server 2012上运行。我要实现的是计算像这样的不同群体的人数

from b in this._context.Benchmark
group b by b.Device into g
select new {
    Device = g.Key,
    Count = g.Count()
}

问题是整个过程非常缓慢,其原因似乎是SQL语句未映射到GROUP BYCOUNT(*),但根据调试器,应用程序请求所有内容并在CPU上执行计数。我从调试器的事件窗口中获得的查询如下:

SELECT [b0].[ID], [b0].[CreateDate], [b0].[Creator], [b0].[Device], [b0].[Environment], [b0].[Machine], [b0].[Name], [b0].[Plugin], [b0].[RunDate]
FROM [Benchmark] AS [b0]
ORDER BY [b0].[Device]

我还可以看到,对于简单的COUNT()来说,用于调试的IIS Express的内存消耗是疯狂的,因此我倾向于认为这是实际的查询。

问题是:如何重新定义查询,使其实际上映射到COUNT()

编辑:我已经在“真实” EF和ctx.Database.Log = Console.Write上尝试了相同的查询,这产生了预期的COUNT()查询,这使我相信这是一个EF Core。

2 个答案:

答案 0 :(得分:0)

请将EF Core升级到2.1.2版。

答案 1 :(得分:0)

  

LINQ表达式'GroupBy([x.Device],[x])'无法翻译   并将在本地进行评估。

     

LINQ表达式'Count()'无法翻译,将被翻译为   本地评估。

上面的日志来自我后来的测试结果,表明尚不支持render<QueryRenderer environment={environment} query={graphql` query MyQuery($exampleUserId: String!) { user(userId: $exampleUserId) { favoriteIceCream } } `} render={({ error, props, retry }) => { // Here, you could call `retry()` to refetch data // or pass it as a prop to a child component. return ( <IceCreamSelectionView refetchData={retry} user={props.user} /> ) }} /> 来将完整的LINQ转换为SQL,然后直接在数据库中执行完整的SQL, EF Core必须首先获取所有数据,然后在本地获取GroupBy结果。因此,如果您的数据量很大,那么性能将非常糟糕。

您必须对简单的SQL进行硬编码才能直接在数据库中进行工作,然后性能才能恢复正常。

我升级到EF Core 2.1.2,在Count()GroupBy中都尝试了以下代码:

MySQL

结果选择器位于MS SQL内部,这将确保是否可以将其转换为正确的SQL,不幸的是,不是。

这是另一个难题,请避免使用var query = _context.Benchmark.GroupBy(x => x.Device, (key, group) => new //Result selector { Device = key, Count = group.Count() }); await query.ToListAsync();

GroupBy

C#代码通过retry function生成以下日志:

Count

这是核心LOGS,它显示尚不支持var query = _context.Benchmark.GroupBy(x => x.Device, (key, group) => new //Result selector { Device = key, Count = group.Select(g => g.Id)//Avoid to use Count }); await query.ToListAsync();

2018-08-24T14:27:26.6737424-04:00 Information 10403 Microsoft.EntityFrameworkCore.Infrastructure
Entity Framework Core 2.1.2-rtm-30932 initialized 'ApplicationDbContext' using provider 'Pomelo.EntityFrameworkCore.MySql' with options: None
2018-08-24T14:27:31.4270317-04:00 Debug 10101 Microsoft.EntityFrameworkCore.Query
Compiling query model: 
'from IGrouping<Device, Benchmark> <generated>_0 in 
    (from Benchmark x in DbSet<Benchmark>
    select [x]).GroupBy([x].Device, [x])
select new <>f__AnonymousType3<Device, int>(
    [<generated>_0].Key, 

        (from Benchmark <generated>_1 in [<generated>_0]
        select [<generated>_1]).Count()
)'
2018-08-24T14:27:31.4319437-04:00 Debug 10104 Microsoft.EntityFrameworkCore.Query
Optimized query model: 
'from IGrouping<Device, Benchmark> <generated>_0 in 
    (from Benchmark x in DbSet<Benchmark>
    join Device x.Device in DbSet<Device>
    on Property([x], "DeviceId") equals Property([x.Device], "Id")
    select [x]).GroupBy([x.Device], [x])
select new <>f__AnonymousType3<Device, int>(
    [<generated>_0].Key, 

        (from Benchmark <generated>_1 in [<generated>_0]
        select [<generated>_1]).Count()
)'

以下是休息日志:

GROUPBY

这是我的环境:

2018-08-24T14:27:31.4431635-04:00 Warning 20500 Microsoft.EntityFrameworkCore.Query
The LINQ expression 'GroupBy([x.Device], [x])' could not be translated and will be evaluated locally.
2018-08-24T14:27:31.4476637-04:00 Warning 20500 Microsoft.EntityFrameworkCore.Query
The LINQ expression 'Count()' could not be translated and will be evaluated locally.
2018-08-24T14:27:31.4511652-04:00 Warning 20500 Microsoft.EntityFrameworkCore.Query
The LINQ expression 'Count()' could not be translated and will be evaluated locally.