DbArithmeticExpression arguments must have a numeric common type

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();

This Linq expression throws this exception:

DbArithmeticExpression arguments must have a numeric common type.

Please Help!

40248 次浏览

实体框架6及更早版本不支持使用 DateTime的算术。你必须使用 数据库函数 * 。所以,你的陈述的第一部分,大概是:

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

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

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

* 实体框架版本6之前的 EntityFunctions

我知道这是一个老问题,但在您的特定情况下,而不是使用 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();

如果您试图将通过固定时间戳移动的存储的日期时间与其他日期时间进行比较,那么这种重构通常是可能的。

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

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

添加 AsEnumable ()将把 SQL 查询转换为实体并允许运行。网络功能。更多信息,请查看这里 关于可枚举的