繁体   English   中英

没有值的 Linq 计数列表 InvalidOperationException

[英]Linq Count List InvalidOperationException on no values

我正在尝试从具有注入 DbContext 的范围后台服务中获取过去一小时内的 CheckIn 数量。

以下查询按预期工作。

var checkins = _dbContext.CheckIns.ToList();
var checkinList = checkins.Where(x => x.LogInTimeStamp.ToUniversalTime() > DateTime.UtcNow.AddHours(-1));
var checkinCount = checkins.Count(x => x.LogInTimeStamp.ToUniversalTime() > DateTime.UtcNow.AddHours(-1));

由于我想保持干净,我尝试将其写在一行中:

var oneLineCountTest = _dbContext.CheckIns.Count(x => x.LogInTimeStamp.ToUniversalTime() > DateTime.UtcNow.AddHours(-1));
var oneLineCountTest2 = (int?)_dbContext.CheckIns.Count(x => x.LogInTimeStamp.ToUniversalTime() > DateTime.UtcNow.AddHours(-1)) ?? 0;

这两行都从 EFCore 返回 InvalidOperationException,我不明白为什么。 任何人都有解释或解决方案?

Exception thrown: 'System.Net.Sockets.SocketException' in System.Net.Sockets.dll
Exception thrown: 'System.OperationCanceledException' in System.Private.CoreLib.dll
Exception thrown: 'System.OperationCanceledException' in System.Private.CoreLib.dll
Exception thrown: 'System.OperationCanceledException' in System.Net.Http.dll
Exception thrown: 'System.OperationCanceledException' in System.Private.CoreLib.dll
Exception thrown: 'System.Threading.Tasks.TaskCanceledException' in System.Net.Http.dll
Exception thrown: 'System.Threading.Tasks.TaskCanceledException' in System.Private.CoreLib.dll
Exception thrown: 'System.Threading.Tasks.TaskCanceledException' in System.Private.CoreLib.dll
Exception thrown: 'System.Threading.Tasks.TaskCanceledException' in System.Private.CoreLib.dll
Exception thrown: 'System.Threading.Tasks.TaskCanceledException' in System.Net.Http.dll
Exception thrown: 'System.Threading.Tasks.TaskCanceledException' in System.Private.CoreLib.dll
Exception thrown: 'System.Threading.Tasks.TaskCanceledException' in System.Private.CoreLib.dll
Exception thrown: 'System.Threading.Tasks.TaskCanceledException' in System.Private.CoreLib.dll
Exception thrown: 'System.Threading.Tasks.TaskCanceledException' in System.Net.Http.dll
Exception thrown: 'System.Threading.Tasks.TaskCanceledException' in System.Private.CoreLib.dll
Exception thrown: 'System.Threading.Tasks.TaskCanceledException' in System.Private.CoreLib.dll
Exception thrown: 'System.Threading.Tasks.TaskCanceledException' in System.Private.CoreLib.dll
Exception thrown: 'System.InvalidOperationException' in Microsoft.EntityFrameworkCore.dll

谢谢

注意本地查询(Linq to Objects)和解释查询(Linq to Entities)之间的区别。

您的第一个代码片段(有效的代码片段)使用解释查询来构建列表。 您向数据库引擎询问元素集合,然后将它们返回并具体化为一个列表(ToList() 调用进行具体化)。 然后在该列表上执行本地查询,这是可能的,因为该列表是本地对象(在内存中)。

第二个代码片段是不同的。 您只是在执行解释查询(使用 Linq to Entities)。 这意味着您要求数据库引擎执行所有查询:计算满足特定规则的元素数量。 只有当 Linq to Entities 能够将 SQL 中的查询转换为由数据库引擎执行时,它才会起作用。 这可能在这里失败。
罪魁祸首可能是使用 AddDays() 方法(请参阅最后的第一个链接)。

请记住:

  • Linq to Object 使用委托在 IEnumerable 上工作。
  • Linq to Entities 使用表达式树在 IQueryable 上工作。

因此,在您的情况下,解释查询中使用的代码可能无法转换为 SQL。

要检查这一点,请尝试简化(即使它没有功能意义)用作 Count 参数的 lambda 中的代码,以查看是否没有更多异常。

看:

如果您尝试此查询,它不会发出任何异常

var dateTimeNow= DateTime.AddHours(-1);

Var oneLineCountTest = _dbContext.CheckIns.Count(x => x.LogInTimeStamp > DateTimeNow);

这意味着 EF 转换器无法将 ToUniversalTime() 转换为 SQL 脚本,这就是您的例外情况。 使用 ToList() 后,所有数据都将移动到 Web 服务器,您可以使用任何对 c# 合法的代码。 我认为,由于您使用的是差异而不是时间,因此您可以计算差异而不转换为 UTC 时间,只要您的应用程序不在世界各地使用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM