«Невозможно вызвать методы для DateTime» и другие ограничения. - PullRequest
8 голосов
/ 27 ноября 2008

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

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

  • Вызов методов, таких как .Date on DateTime
    • обходного пути не найдено
  • string.IsNullOrEmpty
    • просто, просто используйте == "" вместо
  • .Last()
    • мы использовали .OrderByDescending(x => x.WhateverProperty).First()

Ответы [ 5 ]

21 голосов
/ 27 января 2009

По сути, этот список огромен ... это все, что находится за пределами относительно небольшого набора вещей, с которыми обрабатываются . К сожалению, Law of Leaky Abstractions начинает действовать, и у каждого поставщика есть разные ответы ...

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 обрабатываются отдельно. Так что не огромный выбор - но это деталь реализации.

1 голос
/ 29 января 2009

Я создал проблему подключения для String.IsNullOrEmpty ():

Обратная связь: Я хочу использовать string.IsNullOrEmpty в операторах LINQ to SQL.

Не стесняйтесь добавлять свой голос или голосовать за него, или создавать другие проблемы Connect для различных других методов, которые не работают в Linq to SQL. Скрипучее колесо получает смазку.

1 голос
/ 27 января 2009

LINQ - это язык. LINQ-to-SQL компилирует вашу команду LINQ в SQL-запрос. Таким образом, он ограничен обычными ограничениями синтаксиса TSQL или, скорее, элементами, которые могут быть легко преобразованы в него.

Как говорили другие, списки того, что вы не можете сделать, были бы огромными. Это гораздо меньший список того, что вы можете сделать. Общее правило - попытаться определить, как функция, которую вы хотите использовать, будет преобразована в TSQL. Если вам сложно разобраться, не используйте эту функцию (или хотя бы сначала проверьте ее).

Но есть простой способ использовать команды LINQ, которых нет в LINQ-to-SQL. Отделите чистые части вашего кода LINQ от частей LINQ-to-SQL. Другими словами, используйте LINQ-to-SQL для извлечения данных (с любыми необходимыми вам функциями, доступными в LINQ-to_SQL), с помощью команды для помещения их в объект (ToEnumerable, ToList или другие подобные). Это выполняет запрос и извлекает данные локально. Теперь он доступен для полного синтаксиса LINQ.

0 голосов
/ 29 января 2009

Марк Марк Гравелл полностью прав.

Я просто хотел добавить эту деталь для логики дат (и сравнения строк). Поскольку вы используете LinqToSql, вы можете воспользоваться SqlMethods для выполнения тех вещей, которые вы привыкли делать в базе данных.

0 голосов
/ 27 января 2009

У меня была именно эта проблема с 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

Итак, я могу вызывать «.Year» или «.Month» в DateTime, но не «.Date» - я думаю, это сводится к типам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...