私はSQLServerデータベースにヒットするためのさまざまな方法のプロファイリングを行っていました。私は、バニラTSQL、CompiledQuery、およびコンパイルされていないLinqステートメントを行った。CompiledQueryとPlain Linq SQLの生成
予想されたとおりにパフォーマンスが同じ順番で行われましたが、後者の2つをプロファイリングするときに気になることがありました。
CompiledQueryによって生成されたSQLは、普通の古い文で生成されたものよりも優れていました。
ローカル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にエンティティに同じ量のCompiledQueryと同じ量のSQLを与えることは可能ですか?
何の要素がない場合ので、null参照をスローします:あなたは非コンパイルされたクエリからの同じSQLを取得することができるかもしれません(未テスト)
一つの方法は、匿名型に投影することです見つかりました。私の答えに投稿したバージョンは、その動作をしません。 – eglasius
はい。それは意図的です。私は彼の質問でクエリの動作に従っていた。あなたの答えは異なって振る舞います。 –
OPサンプルのような.FirstOrDefault +列アクセスでコンパイルされたクエリを使用すると少し奇妙なので、実際に投げたかどうかはわかりませんでした。あなたのバージョンや鉱山のいずれかを使用するようコンパイルされたバージョンをリファクタリングします。たとえそれらが長くなっても、意図が何であるかをもっとはっきりさせることができます。 – eglasius