如何在entity framework查询中将DateTime转换为TimeSpan

我有Entity Framework 6的LINQ查询:

var timeCapturesQuery = Context.TimeCaptures .Where(t => && t.StartDateTime.TimeOfDay  startTime); 

EndTime和StartTime是TimeSpan类型的参数,StartDateTime和EndDateTime是datetime表上的列。

不幸的是,我在运行时收到此错误:

LINQ to Entities不支持指定的类型成员’TimeOfDay’。 仅支持初始化程序,实体成员和实体导航属性。

如何在此LINQ查询中从DateTime(即SQL中的datetimetime )获取TimeSpan

看起来像DbFunctions.CreateTime正在寻找:

当用作LINQ to Entities查询的一部分时,此方法调用规范的CreateTime EDM函数来创建新的TimeSpan对象。

因此,要在两次之间获得结果,您可以:

 var timeCapturesQuery = Context.TimeCaptures.Where(t => DbFunctions.CreateTime(t.StartDateTime.Hour, t.StartDateTime.Minute, t.StartDateTime.Second) < endTime && DbFunctions.CreateTime(t.EndDateTime.Hour, t.EndDateTime.Minute, t.EndDateTime.Second) > startTime); 

LINQ to Entities不支持属性TimeOfDay,因此您可以尝试使用SqlFunctions.DatePart方法。

您可能还应该将TimeSpans转换为DateTimes。

我认为这应该有效(假设TimeSpans是从当天开始):

 var now = DateTime.Now; var today = new DateTime(now.Year, now.Month, now.Day); var endDateTime = today + endTime; var startDateTime = today + startTime var timeCapturesQuery = Context.TimeCaptures.Where(t => SqlFunctions.DatePart("timeofday", t.StartDateTime) < SqlFunctions.DatePart("timeofday", endDateTime) && SqlFunctions.DatePart("timeofday", t.EndDateTime) > SqlFunctions.DatePart("timeofday", startDateTime)); 

编辑

如评论中所述,DatePart方法不支持特定属性TimeOfTheDay。

也许EntityFunctions.DiffNanoseconds方法可以工作:

 var now = DateTime.Now; var today = new DateTime(now.Year, now.Month, now.Day); var endDateTime = today + endTime; var startDateTime = today + startTime var timeCapturesQuery = Context.TimeCaptures.Where(t => EntityFunctions.DiffNanoseconds(t.StartDateTime, endDateTime).Value < 0 && EntityFunctions.DiffNanoseconds(t.EndDateTime, startDateTime).Value > 0); 

EDIT2

另一个更简单的选项,我觉得可以用来比较DateTimes。

我们已经将TimeSpans转换为DateTimes,我们可以使用LINQ to Entities创建一个简单的条件,它应该可以工作,因为我们没有使用任何DateTimes属性。

 var now = DateTime.Now; var today = new DateTime(now.Year, now.Month, now.Day); var endDateTime = today + endTime; var startDateTime = today + startTime var timeCapturesQuery = Context.TimeCaptures.Where(t => t.StartDateTime < endDateTime && t.EndDateTime > startDateTime); 

看起来Linq2db支持它。

https://github.com/linq2db/linq2db/blob/1ff760181717c73859ab3a5519f76943241d460f/Source/Linq/Expressions.cs

当然,使用新的ORM并不是一个很好的选择。
但我认为这是EF表现最弱的部分。
所以也许是再次思考的好时机。

使用Linq2db,您可以提供自定义SQL逻辑(您需要创建自己的表达式)。 这对我来说从来没有必要,但你可以阅读这个以获取更多细节。