Аргументы 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
Обычно это должен быть объект TimeSpan, в EF выбрасывается исключение.
Наваз Дхандала

Ответы:

247

Арифметика с DateTimeне поддерживается в Entity Framework 6 и более ранних версиях. Вы должны использовать DbFunctions *. Итак, для первой части вашего утверждения что-то вроде:

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

Обратите внимание, что DiffHoursметод принимает Nullable<DateTime>.

Ядро Entity Framwork (при использовании с Sql Server, возможно, другими поставщиками db) поддерживает AddXxxфункции DateTime (например AddHours). Они переведены на DATEADDSQL.

* EntityFunctionsдо Entity Framework версии 6.

Герт Арнольд
источник
2

Я знаю, что это старый вопрос, но в вашем конкретном случае вместо использования, DBFunctionsпредложенного @GertArnold, не могли бы вы просто инвертировать операцию, чтобы удалить рассматриваемую арифметику из Lambda?

В конце концов, clientDateTimeи time24являются фиксированными значениями, поэтому их разницу не нужно пересчитывать на каждой итерации.

Подобно:

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

Этот рефакторинг обычно возможен, если вы пытаетесь сравнить сохраненную дату и время, сдвинутую на временную метку исправления, с другой датой и временем.

SoonDead
источник
У меня была именно такая ситуация, и это помогло. Однако область применения этого решения очень ограничена конкретным типом проблемы.
Zimano
@Zimano. Он решает проблему OP, не требуя от него изменения технологий или взлома. Если его можно реорганизовать таким образом, сделайте это, если нет, сделайте это, как в принятом ответе.
SoonDead
1

В противном случае, если производительность не является истинной целью, вы можете попробовать использовать AsEnumerable(). Итак, это было бы как

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

Добавление AsEnumerable () преобразует запрос SQL в сущность и позволяет запускать на них функции .Net. Для получения дополнительной информации проверьте здесь AsEnumerable

перепутались вверх
источник