Я играл с LINQ-SQL, пытаясь получить повторно используемые фрагменты выражений, которые я могу подключить к другим запросам. Итак, я начал с чего-то вроде этого:
Func<TaskFile, double> TimeSpent = (t =>
t.TimeEntries.Sum(te => (te.DateEnded - te.DateStarted).TotalHours));
Затем мы можем использовать приведенное выше в запросе LINQ, как показано ниже (пример LINQPad):
TaskFiles.Select(t => new {
t.TaskId,
TimeSpent = TimeSpent(t),
})
Это приводит к ожидаемому результату, за исключением того, что запрос на строку генерируется для вставленного выражения. Это видно в LINQPad. Нехорошо.
В любом случае, я заметил метод CompiledQuery.Compile
. Хотя это принимает параметр DataContext
в качестве параметра, я думал, что включу его игнорировать, и попробую те же Func
. Поэтому я получил следующее:
static Func<UserQuery, TaskFile, double> TimeSpent =
CompiledQuery.Compile<UserQuery, TaskFile, double>(
(UserQuery db, TaskFile t) =>
t.TimeEntries.Sum(te => (te.DateEnded - te.DateStarted).TotalHours));
Обратите внимание, что я не использую параметр db
. Однако теперь, когда мы используем этот обновленный параметр, генерируется только 1 SQL-запрос. Выражение успешно переведено в SQL и включено в исходный запрос.
Итак, мой последний вопрос: что делает CompiledQuery.Compile
настолько особенным? Кажется, что параметр DataContext
вообще не нужен, и в этот момент я думаю, что это более удобный параметр для генерации полных запросов.
Будет ли считаться хорошей идеей использовать метод CompiledQuery.Compile
, подобный этому? Это похоже на большой взлом, но он кажется единственным жизнеспособным маршрутом для повторного использования LINQ.
UPDATE
Используя первый Func
в статусе Where
, мы видим следующее исключение:
NotSupportedException: Method 'System.Object DynamicInvoke(System.Object[])' has no supported translation to SQL.
Как показано ниже:
.Where(t => TimeSpent(t) > 2)
Однако, когда мы используем Func
, сгенерированный CompiledQuery.Compile
, запрос выполняется успешно и создается правильный SQL.
Я знаю, что это не идеальный способ повторного использования операторов Where
, но он немного показывает, как генерируется Дерево выражений.