无法翻译 LINQ 表达式“GroupBy([x.Device], [x])”
并将在本地进行评估。
无法翻译 LINQ 表达式“Count()”并将
本地评估。
以上日志来自我后来的测试结果,显示GroupBy&Count()尚不支持将完整的LINQ转换为SQL,然后直接在数据库中执行完整的SQL,现在EF Core必须首先获取所有数据,然后在本地获取 GroupBy 结果。所以,如果你的数据很大,那么性能会很差。
您必须硬编码一个简单的 SQL 才能直接在数据库中执行您的工作,然后性能将恢复正常。
我升级到 EF Core 2.1.2,在MySQL 和MS SQL 中都尝试了以下代码:
var query = _context.Benchmark.GroupBy(x => x.Device,
(key, group) => new //Result selector
{
Device = key,
Count = group.Count()
});
await query.ToListAsync();
结果选择器就在GroupBy 内部,这将确保它是否可以转换为正确的 SQL,不幸的是,它不是。
这里还有一个棘手的问题,避免使用Count:
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();
C# 代码通过this tool 生成以下日志:
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()
)'
这里是核心 LOGS,显示 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.
这是之后的休息日志:
2018-08-24T14:27:31.4608060-04:00 Debug 10107 Microsoft.EntityFrameworkCore.Query
(QueryContext queryContext) => IAsyncEnumerable<<>f__AnonymousType3<Device, int>> _InterceptExceptions(
source: IAsyncEnumerable<<>f__AnonymousType3<Device, int>> _SelectAsync(
source: IAsyncEnumerable<IGrouping<Device, ValueBuffer>> _GroupBy(
source: IAsyncEnumerable<TransparentIdentifier<ValueBuffer, Device>> _ShapedQuery(
queryContext: queryContext,
shaperCommandContext: SelectExpression:
SELECT `x.Device`.`Id`, `x.Device`.`Description`, `x.Device`.`IP`, `x.Device`.`Name`, `x.Device`.`Port`
FROM `Benchmark` AS `x`
INNER JOIN `Device` AS `x.Device` ON `x`.`DeviceId` = `x.Device`.`Id`
ORDER BY `x.Device`.`Id`,
shaper: TypedCompositeShaper<ValueBufferShaper, ValueBuffer, BufferedOffsetEntityShaper<Device>, Device, TransparentIdentifier<ValueBuffer, Device>>),
keySelector: (TransparentIdentifier<ValueBuffer, Device> t0) => t0.Inner,
elementSelector: (TransparentIdentifier<ValueBuffer, Device> t0) => t0.Outer),
selector: (IGrouping<Device, ValueBuffer> <generated>_0 | CancellationToken ct) => Task<<>f__AnonymousType3<Device, int>> _ExecuteAsync(
taskFactories: new Func<Task<object>>[]{ () => Task<object> _ToObjectTask(Task<int> Count(
source: IAsyncEnumerable<ValueBuffer> _ToAsyncEnumerable(<generated>_0),
cancellationToken: queryContext.CancellationToken)) },
selector: (object[] results) => new <>f__AnonymousType3<Device, int>(
<generated>_0.Key,
(int)results[0]
))),
contextType: Sequencer.Updater.Data.ApplicationDbContext,
logger: DiagnosticsLogger<Query>,
queryContext: queryContext)
2018-08-24T14:27:31.4825759-04:00 Debug 20000 Microsoft.EntityFrameworkCore.Database.Connection
Opening connection to database 'TestDB' on server 'localhost,3306'.
2018-08-24T14:27:31.4877302-04:00 Debug 20001 Microsoft.EntityFrameworkCore.Database.Connection
Opened connection to database 'TestDB' on server 'localhost,3306'.
2018-08-24T14:27:31.4901269-04:00 Debug 20100 Microsoft.EntityFrameworkCore.Database.Command
Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT `x.Device`.`Id`, `x.Device`.`Description`, `x.Device`.`IP`, `x.Device`.`Name`, `x.Device`.`Port`
FROM `Benchmark` AS `x`
INNER JOIN `Device` AS `x.Device` ON `x`.`DeviceId` = `x.Device`.`Id`
ORDER BY `x.Device`.`Id`
2018-08-24T14:27:31.4929857-04:00 Information 20101 Microsoft.EntityFrameworkCore.Database.Command
Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT `x.Device`.`Id`, `x.Device`.`Description`, `x.Device`.`IP`, `x.Device`.`Name`, `x.Device`.`Port`
FROM `Benchmark` AS `x`
INNER JOIN `Device` AS `x.Device` ON `x`.`DeviceId` = `x.Device`.`Id`
ORDER BY `x.Device`.`Id`
2018-08-24T14:27:31.5231128-04:00 Debug 20300 Microsoft.EntityFrameworkCore.Database.Command
A data reader was disposed.
2018-08-24T14:27:31.5270399-04:00 Debug 20002 Microsoft.EntityFrameworkCore.Database.Connection
Closing connection to database 'TestDB' on server 'localhost,3306'.
2018-08-24T14:27:31.5303748-04:00 Debug 20003 Microsoft.EntityFrameworkCore.Database.Connection
Closed connection to database 'TestDB' on server 'localhost,3306'.
这是我的环境:
PM> dotnet --info
.NET Core SDK (reflecting any global.json):
Version: 2.1.401
Commit: 91b1c13032
Runtime Environment:
OS Name: Windows
OS Version: 10.0.16299
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\2.1.401\
Host (useful for support):
Version: 2.1.3
Commit: 124038c13e
.NET Core SDKs installed:
2.1.202 [C:\Program Files\dotnet\sdk]
2.1.302 [C:\Program Files\dotnet\sdk]
2.1.400 [C:\Program Files\dotnet\sdk]
2.1.401 [C:\Program Files\dotnet\sdk]
.NET Core runtimes installed:
Microsoft.AspNetCore.All 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]