C# 如何在Linq中将DateTimeOffset转换为DateTime
我有一个返回错误结果的查询:C# 如何在Linq中将DateTimeOffset转换为DateTime,c#,sql-server,linq,C#,Sql Server,Linq,我有一个返回错误结果的查询: return contextProvider .Context .OrderAccounts .Where(orderAccount => listCSRId.Contains(orderAccount.OrderCust.UserId) &&
return contextProvider
.Context
.OrderAccounts
.Where(orderAccount => listCSRId.Contains(orderAccount.OrderCust.UserId) &&
orderAccount.OrderCust.SubmittedDate >= System.Data.Entity.DbFunctions.TruncateTime(startDate)
&& orderAccount.OrderCust.SubmittedDate <= startDate
&& orderAccount.OrderCust.OrderStatusId == (int)OrderStatus.Submitted)
.Select(x => new Order
{
UserId = x.OrderCust.UserId,
FacilityCode = x.FacilityCode,
GreenFlag = x.GreenFlag ?? false,
Payable = x.Payable,
OrderCustId = x.OrderCustId
})
.ToList();
结果不正确的原因是SubmittedDate是Sql Server中的DateTimeOffSet。因此,当存储2017年11月15日晚上11点的本地日期时间时,由于本地时间和格林尼治标准时间之间的偏移,它将存储为2017年11月16日04:00
当查询运行时,startDate只是一个没有时间的日期。因此,需要将表中的SubmittedDate转换为本地日期。那么这个查询就正确了
如何做到这一点?将起始日期转换为UTC,并添加1天,转换并确保提交日期介于两者之间:
return contextProvider
.Context
.OrderAccounts
.Where(orderAccount => listCSRId.Contains(orderAccount.OrderCust.UserId) &&
orderAccount.OrderCust.SubmittedDate >= System.Data.Entity.DbFunctions.TruncateTime(startDate.ToUniversalTime())
&& orderAccount.OrderCust.SubmittedDate < startDate.AddDays(1).ToUniversalTime()
&& orderAccount.OrderCust.OrderStatusId == (int)OrderStatus.Submitted)
.Select(x => new Order {
UserId = x.OrderCust.UserId,
FacilityCode = x.FacilityCode,
GreenFlag = x.GreenFlag ?? false,
Payable = x.Payable,
OrderCustId = x.OrderCustId
})
.ToList();
问题是“startDate”参数是DateTime,而不是DateTimeOffset 当此参数更改为DateTimeOffset时,查询开始正常工作 换句话说,将值为2017-11-15 00:00且偏移量为-5:00的DateTimeOffset转换为2017-11-15 05:00且无偏移量的UTC。我认为EntityFramework/Sql Server足够聪明,可以正确地比较DateTimeOffset,它可以在没有偏移的情况下转换为UTC 因此,现在返回任何大于2017-11-15 05:00的提交日期,这就是我想要的当前日期记录-当地时间为2017-11-15 00:00 时间是一个很难把握的话题,希望我已经正确地解释了这一点
方法是:将Sql Server DateTimeOffset与.net DateTimeOffset进行比较,而不是与DateTime进行比较。为什么不将startDate转换为DateTimeOffset呢?这就是为什么您应该始终在数据库中以UTC存储DateTimes的原因。其他一切都是表示,不属于您的数据库。我意识到这并不能回答你的问题,但它本可以避免,因为时间部分没有被使用。我需要在某个日期提交所有订单,无论何时。如果我转换为DateTimeOffset,然后删除时间部分,它现在将返回错误日期的订单。我尝试了这个,但它对我不起作用。请参见下面的内容。-1因为海报没有验证他或她的假设,即ToUniversalTime是受支持的EF操作,而不是System。NotSupportedException:LINQ to Entities不识别方法“System.DateTimeOffset ToUniversalTime”方法,而且这个方法不能转换成存储表达式。@PaulMSorauer什么让你认为EF是相关的?另外,startDate是一个本地值,而不是SQL列中的EF字段,因此应该在客户机上计算表达式。使用LINQ to SQL/EF Core 2.2.6/EF Core 3.1进行的快速测试表明,该方法工作正常。抱歉。正如你所指出的,我实际上没有意识到startDate是一个局部变量,当我在EF 6中测试时,我在DB中使用了datetimeoffset,这就是它失败的原因。为我的误会道歉。我想把这件事投回去。