У меня есть запрос, который работает не очень хорошо, например, сгенерированный код SQL является неоптимальным.
Исходное утверждение выглядело примерно так (упрощенно):
ctx.Table1.Where(t => ...)
.OrderBy(t => ....)
.Select(t => new {Table1 = t,
SomeProperty = t.Table2.SomeProperty,
SomeProperty2 = t.Table2.SomeProperty2,
AnotherProperty = t.Table3.AnotherProperty,
...
}
Я заглянул в SQL Profiler и обнаружил, что сгенерированный SQL будет присоединяться к одной и той же таблице несколько раз, а выполнение инструкции займет около 1 секунды.
Затем я переписал это утверждение так:
from t in ctx.Table1
join t2 in ctx.Table2 on t.key equals t2.key into lt2
from t2 in lt2.DefaultIfEmpty()
join t3 in ctx.Table3 on t.key equals t3.key into lt3
from t3 in lt3.DefaultIfEmpty()
where t ...
orderby t...
select new {Table1 = t, .... }
Это породило гораздо более приятное утверждение, что при извлечении из SQL-профилировщика и выполнении в Management studio он вдвое быстрее, чем оператор, сгенерированный кодом в предыдущем примере.
Однако при выполнении кода из второго примера время, затраченное на EF для генерации выражения, намного превосходит время, полученное при оптимизации запроса.
Итак, как мне написать оператор номер два как CompiledQuery
. Я в основном не знаю, как вернуть анонимный тип из CompiledQuery
.