【问题标题】:Operand data type time is invalid for add operator操作数数据类型时间对于加法运算符无效
【发布时间】:2013-07-10 19:02:15
【问题描述】:

我有下表:

                  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_TIMESHIFT_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() 均无济于事。

【问题讨论】:

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


【解决方案1】:

我发现了一些问题。

让我们从这里开始:

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

多次致电DateTime.Now 绝不是一个好主意。您正在读取系统时钟三遍。此外,已经有一个用于这个确切目的的属性,所以你可以这样做:

DateTime.Now.TimeOfDay

下一个问题:

c.SHIFT_TIME + c.SHIFT_DURATION

如果轮班时间为晚上 11:00,持续时间为 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

消息 8117,第 16 层,状态 1,第 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 类型,因此您可以将其与您提供给查询的“现在”时间进行比较。

【讨论】:

  • 这太棒了!现在这一切都说得通了。谢谢!
  • 没问题。此外,请确保您了解在没有日期的情况下比较时间的影响。当你超过午夜时,就像从零开始。如果这不是您的想法,您需要将该时间映射到特定日期并改用datetime 比较。
【解决方案2】:

它不知道如何添加两个时间跨度。从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;

?

【讨论】:

  • 它抛出了同样的异常。
猜你喜欢
  • 2012-08-01
  • 2021-11-29
  • 2017-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-11
  • 2017-01-24
相关资源
最近更新 更多