Итак, я проводил профилирование различных способов обращения к моей базе данных SQLServer. Я сделал ванильный TSQL, CompiledQuery и некомпилированный оператор Linq.
Производительность прошла в том же порядке, как и ожидалось, но я заметил кое-что любопытное при профилировании последних двух.
SQL, сгенерированный CompiledQuery, был НАМНОГО лучше, чем сгенерированный простым старым оператором.
Локальная база данных SQLExpress; таблица называется foreignTable, ColumnA - это int, первичный ключ (индексируется); ColumnB является случайным int.
Func<testingDatabaseEntities1, int, int> GetByPK = CompiledQuery.Compile((testingDatabaseEntities1 ft, int key)
=> (ft.foreignTable.Where(x => x.ColumnA == key).FirstOrDefault().ColumnB));
Генерирует
SELECT
[Project1].[ColumnB] AS [ColumnB]
FROM ( SELECT cast(1 as bit) AS X ) AS [SingleRowTable1]
LEFT OUTER JOIN (SELECT TOP (1)
[Extent1].[ColumnB] AS [ColumnB]
FROM [dbo].[foreignTable] AS [Extent1]
WHERE [Extent1].[ColumnA] = @p__linq__1 ) AS [Project1] ON 1 = 1
Что для сгенерированного кода действительно не слишком ужасно.
Но когда я делаю простое утверждение Linq:
entity.foreignTable.Where(x => x.ColumnA == searchForMe).FirstOrDefault().ColumnB
генерирует:
SELECT
[Limit1].[C1] AS [C1],
[Limit1].[ColumnA] AS [ColumnA],
[Limit1].[ColumnB] AS [ColumnB],
[Limit1].[FKColumn] AS [FKColumn]
FROM ( SELECT TOP (1)
[Extent1].[ColumnA] AS [ColumnA],
[Extent1].[ColumnB] AS [ColumnB],
[Extent2].[FKColumn] AS [FKColumn],
1 AS [C1]
FROM [dbo].[foreignTable] AS [Extent1]
LEFT OUTER JOIN (SELECT
[Table_2].[FKColumn] AS [FKColumn],
[Table_2].[SomeText] AS [SomeText]
FROM [dbo].[Table_2] AS [Table_2]) AS [Extent2] ON [Extent1].[ColumnA] = [Extent2].[FKColumn]
WHERE [Extent1].[ColumnA] = @p__linq__7
) AS [Limit1]
Что просто дерьмо.
Таким образом, я предполагаю, что вопрос заключается в следующем: возможно ли дать обычным Linq сущностям такое же количество SQL, как CompiledQuery?