"Не удается вызвать методы в DateTime" и другие ограничения
кто-нибудь знает окончательный список ограничений запросов LINQ to SQL, которые не заблокированы во время компиляции, а также (где это возможно) обходные пути для ограничений?
список, который у нас есть до сих пор:
- вызывающие методы, такие как
.Date
onDateTime
- обходной путь не найден
-
string.IsNullOrEmpty
- простой, просто использовать
== ""
вместо
- простой, просто использовать
-
.Last()
- мы
.OrderByDescending(x => x.WhateverProperty).First()
- мы
5 ответов
в принципе, этот список огромен... это все вне относительно небольшой набор вещей, которые are обрабатывается. К сожалению,Закон Дырявых Абстракций срабатывает, и у каждого провайдера есть разные ответы...
LINQ-to-Objects будет делать все (в значительной степени), так как это делегаты; LINQ-to-SQL и Entity Framework имеют разные наборы поддержки.
в общем, у меня была ярмарка количество успеха с помощью DateTime
свойства и т. д. - Но на самом деле вам придется убедиться, что ваши выражения запросов покрыты модульными тестами, так что если вы когда-либо измените поставщиков (или поставщик обновится), вы знаете, что все это все еще работает.
я думаю, что одно представление-думать в терминах TSQL; нет BOTTOM n
, а есть TOP 1
(re OrderByDescending
); в терминах string.IsNullOrEmpty
, вы могли бы быть вполне буквальным: foo.Bar == null || foo.Bar == ""
; и с DateTime.Date
вы, наверное, можете сделать совсем немного с DATEPART
/ различных компонентов.
другой вариант с LINQ-to-SQL-инкапсулировать логику в UDF-так что вы можете написать UDF, который принимает datetime
и возвращает datetime
, и выставить это через dbml на контекст данных. Затем вы можете использовать это в своих запросах:
where ctx.Date(foo.SomeDate) == DateTime.Today
однако этот подход не обязательно хорошо использует индексы.
обновление:
- поддерживаемые переводы метода и т. д здесь.
- поддерживаемые операции запроса и т. д. являются здесь.
для полной кровавой детали, вы можете посмотреть на System.Data.Linq.SqlClient.PostBindDotNetConverter+Visitor
в отражателе-в частности Translate...
методы; некоторые string
функции обрабатываются отдельно. Так что не огромный selection-но это деталь реализации.
LINQ-это язык. LINQ-to-SQL компилирует вашу команду LINQ в SQL-запрос. Таким образом, он ограничен обычными ограничениями синтаксиса TSQL, а точнее элементами, которые могут быть легко преобразованы в него.
как говорили другие, списки того, что вы не можете сделать, будут огромными. Это гораздо меньший список того, что вы можете сделать. Общее эмпирическое правило-попытаться определить, как функция, которую вы хотите использовать, будет преобразована в TSQL. Если у вас много проблем с вычислением затем не используйте эту функцию (или, по крайней мере, сначала проверьте ее).
но есть простая работа вокруг использования команд LINQ, которые не находятся в LINQ-to-SQL. Отделите чистые части LINQ вашего кода от частей LINQ-to-SQL. Другими словами, сделайте LINQ-to-SQL, чтобы вытащить данные (с любыми необходимыми функциями, доступными в LINQ-to_SQL), с командой, чтобы поместить его в объект (ToEnumerable, ToList или другие подобные). Это выполняет запрос и извлекает данные local. Теперь он доступен для полного синтаксиса LINQ.
Я создал проблему подключения для String.IsNullOrEmpty():
обратная связь: я хочу использовать string.IsNullOrEmpty в операторах LINQ to SQL.
Не стесняйтесь добавлять свой голос или голосовать за него, или создавать другие проблемы подключения для различных других методов, которые не работают в Linq to SQL. Скрипучее колесо получает смазку.
у меня была именно эта проблема с DateTimes, и я обнаружил, что в настоящее время для меня работает следующий обходной путь, но я понимаю, что с большими результирующими наборами это может стать проблемой, поскольку обработка теперь находится в моем приложении, а не в базе данных:
BlogPosts post = (from blogs in blogPosts
where blogs.PostPath == path
select blogs)
.ToList()
.Where(blogs => blogs.Published.Date == publishedDate.Date)
.SingleOrDefault();
обратите внимание на ".ToList () " в середине - это приводит его к нормальному IEnumerable и позволяет мне использовать обычные свойства, которые я ожидал.
единственное, что еще меня немного смущает тот факт, что это юридические в EF:
BlogPosts posts = from blogs in blogPosts
where !blogs.IsDraft
&& blogs.Published.Year == year
&& blogs.Published.Month == month
orderby blogs.Published descending
select blogs
Итак, я могу позвонить ".Год или." Месяц" на дату-время, но не ".Дата " - я думаю, это сводится к типам.
ответ Марка Гравелла полностью прав.
Я просто хотел добавить эту деталь для дата-логики (сравнения). Поскольку вы используете LinqToSql, вы можете воспользоваться SqlMethods, чтобы делать те вещи, которые вы привыкли делать в базе данных.