c# - 比较来自客户端的日期时间和保存在数据库中的日期时间
问题描述
我试图在 Date,Hours,Minutes,Seconds 中的两个日期之间进行比较,但是当我调用 x.CreationTime.TimeOfDay 时出现了可为空的异常。
我认为这个链接答案会解决我的问题,但是在我找到解决方案之后,问题仍然存在 这是我的查询:
public async Task<List<MessageDto>> getMessageHistory(long userId, string code, long HCSId, long Role,DateTime latestMessageDateTime , DateTime messageDateBeforeSeeMore)
{
var result =await _repository.GetAllIncluding(x => x.listOfMessages)
.Where(x => ((x.receiverID == userId|| x.CreatorUserId == userId)
&& x.code== code) && (
x.CreationTime != null
&& x.CreationTime.Date > latestMessageDateTime.Date
&& x.CreationTime.TimeOfDay !=null
&& x.CreationTime.TimeOfDay.Hours > latestMessageDateTime.TimeOfDay.Hours /*<===== this cause the problem if I remove it the query working fine*/
)
&& x.listOfMessages.Any(x => x.HCSId== HCSId)
).OrderBy(message => message.CreationTime).ToListAsync();
return result ;
}
更新:
异常详情:
- $exception {"Object reference not set to an instance of an object."} System.NullReferenceException
+ Data {System.Collections.ListDictionaryInternal} System.Collections.IDictionary {System.Collections.ListDictionaryInternal}
at MyProject.ChatAppService.MessageAppService.<getMessageHistory>d__19.MoveNext() in D:\WorkSpace\MyProject\aspnet-core\src\MyProject.Application\ChatAppService\MessageAppService.cs:line 346
+ TargetSite {Void MoveNext()} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}
更新 2: 我遵循@RandRandom 提到的步骤
我发现的低于异常
The LINQ expression 'DbSet<Message>
.Where(m => m.receiverID == __citizenId_0 || m.CreatorUserId == __userId_0 && m.code == __code_1 && DbSet<HCSMessages>
.Where(h => EF.Property<Nullable<long>>(m, "Id") != null && EF.Property<Nullable<long>>(m, "Id") == EF.Property<Nullable<long>>(h, "messageId"))
.Any(h => h.HCsId == __HCSId_2) && m.CreationTime > __messageDateBeforeSeeMore_3)
.Where(m => m.CreationTime.Date > __latestMessageDateTime_Date_4)
.Where(m => m.CreationTime.TimeOfDay.Hours > __latestMessageDateTime_TimeOfDay_Hours_5)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
解决方案
问题:
异常没有包含更多有用信息的内部异常?
尝试回答:
一个疯狂的猜测是,唯一实际上可以为 null 的东西是x.listOfMessages
因为它是您正在使用的唯一引用类型,其他一切都是结构。
您可以通过将查询拆分为多个部分并一个接一个地分别具体化每个查询来“轻松”缩小错误范围。
所以首先像这样重写你的查询:
public async Task<List<MessageDto>> getMessageHistory(long userId, string code, long HCSId, long Role,DateTime latestMessageDateTime , DateTime messageDateBeforeSeeMore)
{
IEnumerable<MessageDto> result = await _repository.GetAllIncluding(x => x.listOfMessages);
result = result.Where(x => x.receiverID == userId || x.CreatorUserId == userId);
result = result.Where(x => x.code == code);
//dropped the null checks for DateTime and TimeOfDay, since NULL should be impossible
result = result.Where(x => x.CreationTime.Date > latestMessageDateTime.Date );
result = result.Where(x => x.CreationTime.TimeOfDay.Hours > latestMessageDateTime.TimeOfDay.Hours);
result = result.Where(x => x.listOfMessages.Any(x => x.HCSId== HCSId));
result = result.OrderBy(message => message.CreationTime);
return (List<MessageDto>)result;
}
在此之后添加.ToListAsync()
从顶部开始的每一行,并随着每个成功的步骤将其向下移动一个位置。
因此,在您的第一次测试中,将第一行更改为:
IEnumerable<MessageDto> result = await _repository.GetAllIncluding(x => x.listOfMessages).ToListAsync(); //added .ToListAsync()
对于第二个测试,ToListAsync()
从第一行中删除并将其添加到第二行,第一行和第二行应该如下所示:
IEnumerable<MessageDto> result = await _repository.GetAllIncluding(x => x.listOfMessages); //removed .ToListAsync()
result = result.Where(x => (x.receiverID == userId || x.CreatorUserId == userId)).ToListAsync(); //added .ToListAsync()
使用这种方法,您可以分别具体化每个条件,并且可以找出哪些条件会失败。
编辑:
发生“Update2”中的错误是因为您正在执行无法转换为 SQL 查询的操作。
一般来说,要解决此问题,您有两个选择
在本地运行不受支持的表达式,以跳过将表达式转换为 SQL 的必要性
为此,您必须在不支持之前评估所有表达式,当枚举发生时会发生评估
IQueryable
,简单的方法是例如调用ToList()
,ToArray()
或AsEnumerable()
,在此之后您的表达式将针对 anIEnumerable<T>
而不是IQueryable<T>
如果有合适的,请使用 DbFunctions - https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbfunctions - 或编写您自己的函数 - https://khalidabuhakmeh.com/add-custom -database-functions-for-entity-framework-core
但在你的情况下,我会质疑你的整体表达,为什么要单独比较日期和时间
result = result.Where(x => x.CreationTime.Date > latestMessageDateTime.Date );
result = result.Where(x => x.CreationTime.TimeOfDay.Hours > latestMessageDateTime.TimeOfDay.Hours);
而不是简单地比较DateTime
结构?
result = result.Where(x => x.CreationTime > latestMessageDateTime );
推荐阅读
- c++ - 如何用不同大小的向量初始化二维向量
- symfony - Doctrine 不使用模式或数据库前缀创建表,也不使用 `schema` 属性
- javascript - 如何将 11 到 30 之间的整数乘以 0.015?
- google-chrome-devtools - Chrome 或 FF 网络开发工具,如何在网络监视器关闭的情况下重新加载页面?
- android - startLeScan 方法没有得到任何结果
- android - 我需要将设备注册令牌发送到 fcm 控制台吗?
- authentication - HttpClientHandler.ClientCertificates 是否只导致叶证书或整个证书层次结构被发送到服务器?
- circuit-sdk - 通过 REST API 将文件上传到 Circuit Conversation - 后端上传
- javascript - 在这种情况下,有没有更好的方法来使用过滤器数组?
- sonarqube - AEM 源代码扫描的 SonarQube 参考错误