操作数数据类型时间对于添加运算符无效

时间:2013-07-10 19:02:16

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

我有下表:

                  SHIFT
 ----------------------------------------
| SHIFT_ID | SHIFT_TIME | SHIFT_DURATION |
| -------------------------------------- |
| 1        | 00:00:00   | 01:00:00       |
| 2        | 01:00:00   | 01:00:00       |
| 3        | 02:00:00   | 01:00:00       |
 ----------------------------------------

此处, SHIFT_TIME SHIFT_DURATION 属于TimeSpan类型。

现在,当我运行以下查询时:

var query = from c in SHIFT
            where c.SHIFT_TIME + c.SHIFT_DURATION >=
            new TimeSpan(DateTime.Now.Hour,
                         DateTime.Now.Minute,
                         DateTime.Now.Second)
            select c;

我收到以下错误:Operand data type time is invalid for add operator.

为什么这样做?我该如何规避这个错误?

修改:我尝试同时使用.Add().CompareTo()无效。

2 个答案:

答案 0 :(得分:3)

我看到了一些问题。

让我们从这里开始:

new TimeSpan(DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second)

多次调用DateTime.Now绝不是一个好主意。您正在读取系统时钟三次。此外,还有一个用于此目的的属性,因此您可以这样做:

DateTime.Now.TimeOfDay

下一个问题:

c.SHIFT_TIME + c.SHIFT_DURATION

如果换班时间是晚上11点,且持续时间是2小时,那么您可能期望凌晨1点,但相反,您将获得25小时。 (实际上你会得到" 1天1小时"。)所以当你到了一天的时间(例如12:30)时,你可能会变得与众不同结果超出预期。

下一个问题:

您没有提到这一点,但看起来您实际上正在使用LINQ-to-Entities,作为Entity Framework的一部分,附加到SQL Server。 (我更新了你的标签。)我可以告诉你,因为你收到的错误信息实际上是一个SQL Server错误信息。您可以在SQL Server Management Studio中重现它,如下所示:

declare @t1 time, @t2 time
set @t1 = '1:00'
set @t2 = '1:00'
print @t1 + @t2
  

Msg 8117,Level 16,State 1,Line 4
  操作数数据类型时间对于添加运算符无效。

虽然您可以在.Net中添加两个TimeSpan类型,但您无法在SQL Server中添加两个time类型。这是因为time表示一天中的某个时间,而TimeSpan主要表示测量的时间长度。 (从技术上讲,我上面提到的DateTime.TimeOfDay属性违反了TimeSpan类型的设计目的,但允许这样做,因为.Net中没有Time类型。)

因此,当您执行原始查询时,time类型的列被添加到一起,这是不允许的。 time类型的最大值为23:59:59.9999999,因此我无法获得前面提到的25小时结果。

该怎么做?

要在SQL查询中操作日期和时间,您需要使用EntityFuntionsSqlFunctions类的方法。这些将转换为查询中SQL的本机函数。

我相信这会做你想要的:

var query = from c in SHIFT
            where EntityFunctions.AddMinutes(c.SHIFT_TIME,
                    EntityFunctions.DiffMinutes(TimeSpan.Zero, c.SHIFT_DURATION))
                  >= DateTime.Now.TimeOfDay
            select c;

这将构建一个类似于以下的sql查询(假设它现在是1:00):

SELECT * FROM SHIFT WHERE DATEADD(minute,
                                    DATEDIFF(minute, 0, SHIFT_DURATION),
                                    SHIFT_TIME
                                 ) >= '1:00'

SQL Server将隐式地将time输入类型强制转换为datetime,以便它可以与DATEADD函数一起使用。它还会将结果转换回time类型,因此您可以将其与" now"进行比较。你提供给查询的时间。

答案 1 :(得分:1)

它不知道如何添加两个时间盘。从this site使用TimeSpan.Add()

然后使用TimeSpan.Compare()


你正在做什么

var query = from c in SHIFT
        where TimeSpan.Compare(c.SHIFT_TIME.Add(c.SHIFT_DURATION), 
                new TimeSpan(DateTime.Now.Hour,
                             DateTime.Now.Minute,
                             DateTime.Now.Second)).Equals(1)
        select c;