Аргументи 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?
шахкалпеш

noramlly, яка повинна бути об'єктом 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, можливо, іншими постачальниками db) підтримує функції DateTime AddXxx(як AddHours). Вони переведені на DATEADDSQL.

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


2

Я знаю, що це давнє питання, але у вашому конкретному випадку замість того DBFunctions, щоб запропонувати @GertArnold, ви не могли просто перевернути операцію, щоб перенести арифметику, про яку йдеться в лямбда?

Адже 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();

Цей рефактор, як правило, можливий, якщо ви намагаєтеся порівняти збережений час дати, зміщений часовою позначкою виправлення, з іншим часом.


У мене була така точна ситуація, і це допомогло. Однак обсяг цього рішення дуже обмежений конкретним видом проблеми.
Зімано

@ Zimano Він вирішує проблему ОП, не вимагаючи від нього змінити технології та не вдаватися до хаків. Якщо це можна буде відновити так, як це зробити, то зробіть це, якщо ні, то зробіть так, як у прийнятій відповіді.
Незабаром

1

Інший спосіб, якщо продуктивність не є справжньою метою, ви можете спробувати використовувати AsEnumerable(). Отже, було б як

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

Додавання AsEnumerable () перетворить SQL-запит у сутність та дозволить запускати на них функції .Net. Для отримання додаткової інформації перегляньте тут AsEnumerable

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.