LINQ to Entities does not recognize the method 'System.DateTime AddDays(Double)'

227
15 февраля 2018, 12:34

Внимание! Это перевод вопроса Linq to EntityFramework DateTime.

Также смотри близкий по смыслу вопрос: Linq to Entities не распознает метод

У меня есть приложение c# использующее Entity Framework.

Я делаю запрос к таблице Article, имеющей поле startDate и хочу получить записи из базы, которые удовлетворяют условиям DateTime.Now > startDate и (startDate + period) > DateTime.Now:

Context.Article
    .Where(p => p.StartDate < DateTime.Now)
    .Where(p => p.StartDate.AddDays(p.Period) > DateTime.Now)

При запуске этого кода я получаю ошибку:

LINQ to Entities does not recognize the method 'System.DateTime AddDays(Double)' method, and this method cannot be translated into a store expression.

Как это исправить?

Answer 1

Когда происходит выполнение Linq-запроса, ваши условия в where, которые записаны на языке c# должны быть преобразованы в SQL-запрос и в ошибке сообщается о том, что LINQ to Entities неизвестно, как преобразовывать AddDays из c# кода в код SQL.

Есть два варианта решения этой проблемы.

Первый вариант подразумевает, что вы отказываетесь от того, чтобы выполнять эти условия на сервере и перенесёте на клиент. Так как Linq To Objects знает, как обработать AddDays - то ошибка пропадёт:

Context.Article.Where(p => p.StartDate < DateTime.Now)
               .ToList()
               .Where(p => p.StartDate.AddDays(p.Period) > DateTime.Now);

Минусы этого подхода очевидны: вы качаете лишние данные с SQL-сервера в память клиента и эти расходы могут быть весьма значительны.

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

А вот если бы у вас запрашивался список статей какого-то определённого автора за интервал времени, то вероятно этой дополнительной нагрузкой для клиента можно было бы пренебречь.

Второй вариант решения подразумевает, что у вас версия .Net 4.0 или выше и вы можете воспользоваться EntityFunctions.AddDays:

Context.Article.Where(p => p.StartDate < DateTime.Now)
               .Where(p => EntityFunctions.AddDays(p.StartDate, p.Period)
                   > DateTime.Now);

В данном подходе sql-выражение выполняется на сервере, поэтому этот вариант решения является более предпочтительным.

Разумеется, помимо AddDate в EntityFunctions есть и определения для других функций.

В EF6 вместо EntityFunctions вам следует использовать аналог – DbFunctions, например для AddDays есть аналог.

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

READ ALSO
Как описать свойства в модели C# MVC

Как описать свойства в модели C# MVC

Добрый день! Подскажите, как должны выглядеть свойства модели, если есть следующее представлением клиента (JSON только как пример):

239
Пауза во время цикла c# [дубликат]

Пауза во время цикла c# [дубликат]

На данный вопрос уже ответили:

258
Разный typeof в chrome

Разный typeof в chrome

Использую библиотеку amchartsВ chrome в режиме инкогнито код console

301