Расширение EF4 SQL Generation - PullRequest
       18

Расширение EF4 SQL Generation

6 голосов
/ 08 июня 2010

Мы используем EF4 в довольно большой системе и иногда сталкиваемся с проблемами из-за невозможности преобразования EF4 определенных выражений в SQL. В настоящее время нам нужно либо выполнить некоторую сложную работу (DB / Code), либо просто принять удар по производительности и разрешить выполнение запроса в памяти.

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

В идеале нам бы хотелось расширить возможности генерации SQL поставщика EF4 SQL. Очевидно, есть некоторые вещи, такие как вызовы методов .Net, которые всегда должны быть на стороне клиента, но некоторые функции, такие как сравнение дат (например, [Группировать по неделям в Linq до Entities ), должны быть выполнимыми.

Я гуглил, но, возможно, я использую неверную терминологию, так как все, что я получаю, это информацию о новых возможностях EF4 SQL Generation.

Для такой гибкой и расширяемой среды я бы удивился, если бы это было невозможно. В моей голове я представляю себе наследование от [SQL 2008] провайдера и расширение его для обработки дополнительных выражений / аналогичных в дереве выражений, которое ему дано для преобразования в SQL.

Любая помощь / указатели приветствуются.

Мы используем VS2010 Ultimate, .Net 4 (не клиентский профиль) и EF4. Приложение работает в ASP.Net и работает в 64-битной среде на случай, если что-то изменится.

Обновление: В ответ на некоторые просьбы о разъяснениях;

Мы используем подход, основанный на коде, и у нас есть консольное приложение, которое создает базу данных и заполняет некоторые справочные таблицы.

Я бы предпочел держаться подальше от Хранимых процедур, если они также не могут быть сгенерированы подобным образом. В настоящее время новые версии базы данных генерируются по мере необходимости, а отдельный процесс переносит / синхронизирует данные. все , что мы в настоящее время делаем в отношении базы данных, использует сущности. Я признаю, что не могу дать вескую причину, но запуск сценариев SQL для генерации хранимых процедур выглядит неправильно в этом сценарии - но, пожалуйста, исправьте меня, если я ошибаюсь.

Что касается конкретного сценария, я боюсь, что не смогу получить его из нашего кода, не пройдя длинное упражнение с бюрократизмом - ссылка , упомянутая выше , является хорошим примером такого рода. вещей, которые мы пытаемся достичь. В этом примере реализован механизм разрешения арифметики дат:

DateTime firstDay = GetFirstDayOfFirstWeekOfYear();
var userTimes = from t in context.TrackedTimes
                group t by new {t.User.UserName, WeekNumber = (t.TargetDate - firstDay).Days / 7} into ut
                select new
                {
                    UserName = ut.Key.UserName,
                    WeekNumber = ut.Key.WeekNumber,
                    Minutes = ut.Sum(t => t.Minutes)
                };

Я вижу способ, которым это можно сделать, используя только SQL, но не то, как это можно сделать с помощью LINQ-To-Entities (на стороне сервера).

Ответы [ 2 ]

9 голосов
/ 08 июня 2010

Я бы рекомендовал сначала взглянуть на EntityFunctions (универсальный) или SqlFunctions (только для SQL Server), которые предоставляют множество встроенных функций базы данных в обычном запросе LINQ to Entities. , Если этого недостаточно, вы можете использовать EdmFunctionAttribute для сопоставления встроенной функции базы данных или пользовательской хранимой процедуры. Третий вариант - попытаться заставить его работать как запрос Entity SQL.

Последнее решение, которое вы предложили - написание провайдера EF, - довольно тяжеловесное. Может быть возможно написать EF-провайдера, который обернет существующего SQL-провайдера, но вам придется по крайней мере изменить некоторые деревья выражений на Entity SQL. Для MSDN Code выпущены очень простые оболочки EF-провайдера. Впрочем, я бы отнесся к этому как к крайнему средству.

1 голос
/ 08 июня 2010

Преобразование ваших LINQ-запросов на основе .NET в SQL выполняется LINQ To Entities Provider . Я не верю, что основной процесс перевода / компиляции, который является чрезвычайно сложным, является расширяемым. Вам придется написать свой собственный провайдер с нуля.

Мне еще не приходилось сталкиваться с любым запросом, который может быть представлен в SQL, который не может быть выражен в LINQ. Если у вас есть запрос, который сложно написать в виде запроса LINQ, рассматривали ли вы вместо этого использование хранимых процедур? Было бы полезно, если бы вы могли привести несколько примеров запросов, которые не будут преобразованы.

UPDATE:

Другим вариантом является создание расширенных методов расширения, которые используют пользовательские выражения для формирования вашего запроса. Вот хороший пример, который имитирует функцию Contains () для выполнения запросов типа «где в»:

Обходной путь 'Contains ()' с использованием Linq to Entities?

...