DbArithmeticExpression参数必须具有数字通用类型


120
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什么?
shahkalpesh 2012年

通常,它应该是TimeSpan的对象,但会抛出EF异常。
Nawaz Dhandala 2012年

Answers:


247

DateTimeEntity Framework 6和更早版本不支持算术运算符。您必须使用DbFunctions *。因此,对于您的陈述的第一部分,类似:

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

请注意,该DiffHours方法接受Nullable<DateTime>

实体Framwork核心(与Sql Server一起使用时,也许是其他数据库提供程序)支持DateTime AddXxx函数(如AddHours)。它们已翻译成DATEADDSQL。

* EntityFunctions在Entity Framework版本6之前。


2

我知道这是一个老问题,但是在您的特定情况下,不是DBFunctions像@GertArnold所建议的那样使用,您难道不就将运算从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

@Zimano它可以解决OP的问题,而无需他更改技术或诉诸黑客。如果可以这样重构,则执行此操作,否则,请按照接受的答案中的说明进行操作。
很快死了

1

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

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

添加AsEnumerable()会将SQL查询转换为实体,并允许在其上运行.Net函数。有关更多信息,请在此处查看有关AsEnumerable的信息。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.