【问题标题】:DbArithmeticExpression arguments must have a numeric common typeDbArithmeticExpression 参数必须具有数字通用类型
【发布时间】:2012-04-06 21:40:53
【问题描述】:
TimeSpan time24 = new TimeSpan(24, 0, 0);
TimeSpan time18 = new TimeSpan(18, 0, 0);    

// first get today's sleeping hours
List<Model.Sleep> sleeps = context.Sleeps.Where(
    o => (clientDateTime - o.ClientDateTimeStamp < time24) && 
          o.ClientDateTimeStamp.TimeOfDay > time18 && 
          clientDateTime.TimeOfDay < time18 && 
          o.UserID == userid).ToList(); 

这个 Linq 表达式抛出这个异常:

DbArithmeticExpression arguments must have a numeric common type.

请帮忙!

【问题讨论】:

  • clientDateTime - o.ClientDateTimeStamp的结果是什么?
  • 通常应该是TimeSpan的对象,在EF中抛出异常。

标签: c# entity-framework ado.net


【解决方案1】:

Entity Framework 6 及更早版本不支持 DateTime 的算术运算。您必须使用DbFunctions*。因此,对于您声明的第一部分,类似于:

var sleeps = context.Sleeps(o =>
    DbFunctions.DiffHours(o.ClientDateTimeStamp, clientDateTime) < 24);

注意DiffHours 方法接受Nullable&lt;DateTime&gt;

Entity Framwork 核心(与 Sql Server 一起使用时,可能是其他数据库提供程序)支持 DateTime AddXxx 函数(如 AddHours)。它们在 SQL 中被翻译成DATEADD

*EntityFunctions Entity Framework 版本 6 之前的版本。

【讨论】:

    【解决方案2】:

    我知道这是一个老问题,但在您的具体情况下,您不能像 @GertArnold 建议的那样使用 DBFunctions,而是将运算从 Lambda 中移出有问题的算术?

    毕竟clientDateTimetime24 是固定值,因此不需要在每次迭代中重新计算它们的差异。

    喜欢:

    TimeSpan time24 = new TimeSpan(24, 0, 0);
    TimeSpan time18 = new TimeSpan(18, 0, 0);    
    
    var clientdtminus24 = clientDateTime - time24;
    
    // first get today's sleeping hours
    List<Model.Sleep> sleeps = context.Sleeps.Where(
        o => (clientdtminus24 < o.ClientDateTimeStamp) && 
              o.ClientDateTimeStamp.TimeOfDay > time18 && 
              clientDateTime.TimeOfDay < time18 && 
              o.UserID == userid).ToList();
    

    如果您尝试将存储的日期时间偏移固定时间戳与其他日期时间进行比较,则通常可以进行此重构。

    【讨论】:

    • 我遇到过这种情况,这很有帮助。但是,此解决方案的范围非常有限,仅限于特定类型的问题。
    • @Zimano 它解决了 OPs 问题,而不需要他改变技术或求助于黑客。如果可以像这样重构,那么就这样做,如果不能,就像接受的答案那样做。
    【解决方案3】:

    另外,如果性能不是真正的目标,您可以尝试使用AsEnumerable()。 所以,就像

    List<Model.Sleep> sleeps = context.Sleeps.AsEnumerable().Where(....
    

    添加 AsEnumerable() 会将 SQL 查询转换为实体,并允许在它们上运行 .Net 函数。欲了解更多信息,请查看about AsEnumerable

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-21
      • 2022-08-21
      • 1970-01-01
      相关资源
      最近更新 更多