我有下表:
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()
无效。
答案 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查询中操作日期和时间,您需要使用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将隐式地将time
输入类型强制转换为datetime
,以便它可以与DATEADD
函数一起使用。它还会将结果转换回time
类型,因此您可以将其与" now"进行比较。你提供给查询的时间。
答案 1 :(得分:1)
它不知道如何添加两个时间盘。从this site使用TimeSpan.Add()
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;