DbArithmeticExpression参数必须具有数字公共类型

时间:2012-03-22 10:25:47

标签: c# entity-framework ado.net

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.

请帮助!

3 个答案:

答案 0 :(得分:220)

Entity Framework 6及更早版本不支持DateTime的算术运算。你必须使用DbFunctions *。因此,对于陈述的第一部分,例如:

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

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

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

实体框架版本6之前的

* EntityFunctions

答案 1 :(得分: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();

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

答案 2 :(得分:1)

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

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

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