我有下表:
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;
我收到以下错误:操作数数据类型时间对于添加运算符无效.
为什么这样做呢?我该如何避免这个错误?
编辑:我尝试使用.Add()和.CompareTo()无济于事.
解决方法:
我看到了一些问题.
让我们从这里开始:
new TimeSpan(DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second)
多次调用DateTime.Now绝不是一个好主意.您正在读取系统时钟三遍.另外,已经有一个用于此确切目的的属性,因此您可以执行以下操作:
DateTime.Now.TimeOfDay
下一个问题:
c.SHIFT_TIME + c.SHIFT_DURATION
如果轮班时间是11:00 PM,持续时间是2个小时,那么您可能希望是1:00,但是您将获得25个小时. (实际上,您将获得“ 1天1小时”.)因此,当您将其设置为一天中的某个时间(例如12:30 AM)时,可能会得到与预期不同的结果.
下一个问题:
您没有提到这一点,但看起来您实际上是在将LINQ-to-Entities作为附加到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
Operand data type time is invalid for add operator.
虽然可以在.Net中添加两种TimeSpan类型,但不能在SQL Server中添加两种时间类型.这是因为时间旨在表示一天中的某个时间,而TimeSpan主要表示所测量的时间长度. (从技术上讲,我上面提到的DateTime.TimeOfDay属性违背了TimeSpan类型的设计目的,但是由于.Net中没有Time类型,因此可以使用它.)
因此,当您执行原始查询时,时间类型的列会加在一起,这是不允许的.时间类型的最大值是23:59:59.9999999,因此不可能获得我之前提到的25小时结果.
该怎么办?
要在SQL查询中操作日期和时间,您需要使用EntityFuntions
或SqlFunctions
类的方法.这些将转换为查询中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会将时间输入类型隐式转换为日期时间,以便可以与DATEADD函数一起使用.它还会将结果转换回时间类型,因此您可以将其与提供给查询的“现在”时间进行比较.