如何在实体框架查询中将DateTime转换为TimeSpan

时间:2016-10-02 22:57:26

标签: c# sql-server entity-framework linq

我在实体框架6中有这个LINQ查询:

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

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

不幸的是,我在运行时遇到了这个错误:

  

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

如何在此LINQ查询中从DateTime(即SQL中TimeSpan的{​​{1}})获取time

3 个答案:

答案 0 :(得分:5)

看起来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);

答案 1 :(得分:2)

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);

答案 2 :(得分:0)

看起来Linq2db支持它。

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

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

使用Linq2db,您可以提供自定义SQL逻辑(您需要创建自己的表达式)。这对我来说从来没有必要,但您可以阅读this了解更多详情。