"Не удается вызвать методы в DateTime" и другие ограничения

кто-нибудь знает окончательный список ограничений запросов LINQ to SQL, которые не заблокированы во время компиляции, а также (где это возможно) обходные пути для ограничений?

список, который у нас есть до сих пор:

  • вызывающие методы, такие как .Date on DateTime
    • обходной путь не найден
  • 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, чтобы делать те вещи, которые вы привыкли делать в базе данных.