LINQクエリに問題があります。クエリは次のようになります。テーブルで定義された5次元の問題空間からListパラメータを使用してLINQクエリをコンパイルする方法はありますか?
Dim elements = (From filterSum In dataContext.GetTable(Of TblFilterSum)
Join filterProdInSum In dataContext.GetTable(Of TblFilterProdsInSum)
On filterSum.SumID Equals filterProdInSum.SumID
Join filterProd In dataContext.GetTable(Of TblFilterProd)
On filterProdInSum.ProdID Equals filterProd.ProdID
Join filterElementInProd In dataContext.GetTable(Of TblFilterElementsInProd)
On filterProd.ProdID Equals filterElementInProd.ProdID
Join filterElement In dataContext.GetTable(Of TblFilterElement)
On filterElementInProd.ElementID Equals filterElement.ElementID
Where sumIDs.Contains(filterSum.SumID)).Select(Function(r) New With {.SumID = r.filterSum.SumID, .ProdID = r.filterProd.ProdID, .filterElement = r.filterElement, .IsNotSum = r.filterSum.IsNot, .IsNotProd = r.filterProd.IsNot}).ToList
このクエリ負荷を記録、:
tblFilterSum
tblFilterProdsInSum
tblFilterProd
tblFilterElementsInProd
tblFilterElement
私はWhere
句で使用するフィルタはtblFilterSum.SumID
がsumIDs
呼ばList(Of Integer)
の内側にあるということです。 Linqクエリは論理的に完璧で、私が必要とする結果しかありません。ただし、実行には平均で20秒の実行時間が必要です。これは、LINQクエリを生成SQLです:
-- Region Parameters
DECLARE @p0 Int = 12168
DECLARE @p1 Int = 12157
DECLARE @p2 Int = 11948
DECLARE @p3 Int = 11951
DECLARE @p4 Int = 11952
DECLARE @p5 Int = 11950
DECLARE @p6 Int = 11961
DECLARE @p7 Int = 12153
DECLARE @p8 Int = 12154
DECLARE @p9 Int = 12149
DECLARE @p10 Int = 12158
DECLARE @p11 Int = 11954
DECLARE @p12 Int = 11955
DECLARE @p13 Int = 11956
DECLARE @p14 Int = 11957
DECLARE @p15 Int = 11958
DECLARE @p16 Int = 11959
DECLARE @p17 Int = 12159
DECLARE @p18 Int = 12164
DECLARE @p19 Int = 12150
DECLARE @p20 Int = 12151
DECLARE @p21 Int = 12152
DECLARE @p22 Int = 12156
DECLARE @p23 Int = 12161
DECLARE @p24 Int = 12167
DECLARE @p25 Int = 11962
DECLARE @p26 Int = 12155
DECLARE @p27 Int = 12183
DECLARE @p28 Int = 12182
DECLARE @p29 Int = 12165
DECLARE @p30 Int = 12166
DECLARE @p31 Int = 11953
DECLARE @p32 Int = 12163
DECLARE @p33 Int = 12181
DECLARE @p34 Int = 12180
DECLARE @p35 Int = 12160
DECLARE @p36 Int = 12162
-- EndRegion
SELECT [t0].[SumID], [t2].[ProdID], [t4].[ElementID], [t4].[Field], [t4].[Operator], [t4].[Result], [t4].[IsCustom], [t4].[IsNot], [t4].[DisplayOrder], [t4].[FilteredColumnID], [t4].[ColumnMappingID], [t4].[ResultPointerToAssetPath], [t4].[ResultCustomColumnMappingID], [t0].[IsNot] AS [IsNotSum], [t2].[IsNot] AS [IsNotProd]
FROM [dbo].[tblFilterSum] AS [t0]
INNER JOIN [dbo].[tblFilterProdsInSum] AS [t1] ON [t0].[SumID] = [t1].[SumID]
INNER JOIN [dbo].[tblFilterProd] AS [t2] ON [t1].[ProdID] = [t2].[ProdID]
INNER JOIN [dbo].[tblFilterElementsInProd] AS [t3] ON [t2].[ProdID] = [t3].[ProdID]
INNER JOIN [dbo].[tblFilterElement] AS [t4] ON [t3].[ElementID] = [t4].[ElementID]
WHERE [t0].[SumID] IN (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11, @p12, @p13, @p14, @p15, @p16, @p17, @p18, @p19, @p20, @p21, @p22, @p23, @p24, @p25, @p26, @p27, @p28, @p29, @p30, @p31, @p32, @p33, @p34, @p35, @p36)
-- Context: SqlProvider(Sql2008) Model: MappedMetaModel Build: 4.6.1055.0
GO
これは私がゆえの問題は、LINQの下には、.NET Frameworkの4.0は、クエリにそれが実行されるたびにコンパイルすることで、直接それを実行した場合、即座に実行され、何のキャッシュがありませんまったく。ただし、結果をキャッシュする可能性があります。System.Data.Linq.CompiledQuery.Compileは、LINQクエリをコンパイルできる便利な方法です。返されるFunc
は、.NET Framework 4.0で使用されるalways-compile戦略を回避するために、さまざまなパラメータで何度も何度も再利用できます。考えられるそれぞれのクエリに対して一意の署名を作成し、共有ディクショナリを使用して、あらゆる種類のクエリを一度コンパイルし、キャッシュに格納して後で他の属性と再利用することができます。これは良いとは言えますが、可能な用途を見てみましょう:
Public Shared Function Compile(Of TArg0 As DataContext, TResult)(query As Expression(Of Func(Of TArg0, TResult))) As Func(Of TArg0, TResult)
Public Shared Function Compile(Of TArg0 As DataContext, TArg1, TResult)(query As Expression(Of Func(Of TArg0, TArg1, TResult))) As Func(Of TArg0, TArg1, TResult)
Public Shared Function Compile(Of TArg0 As DataContext, TArg1, TArg2, TResult)(query As Expression(Of Func(Of TArg0, TArg1, TArg2, TResult))) As Func(Of TArg0, TArg1, TArg2, TResult)
Public Shared Function Compile(Of TArg0 As DataContext, TArg1, TArg2, TArg3, TResult)(query As Expression(Of Func(Of TArg0, TArg1, TArg2, TArg3, TResult))) As Func(Of TArg0, TArg1, TArg2, TArg3, TResult)
Public Shared Function Compile(Of TArg0 As DataContext, TArg1, TArg2, TArg3, TArg4, TResult)(query As Expression(Of Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TResult))) As Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TResult)
Public Shared Function Compile(Of TArg0 As DataContext, TArg1, TArg2, TArg3, TArg4, TArg5, TResult)(query As Expression(Of Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TResult))) As Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TResult)
Public Shared Function Compile(Of TArg0 As DataContext, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TResult)(query As Expression(Of Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TResult))) As Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TResult)
Public Shared Function Compile(Of TArg0 As DataContext, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TResult)(query As Expression(Of Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TResult))) As Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TResult)
Public Shared Function Compile(Of TArg0 As DataContext, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TResult)(query As Expression(Of Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TResult))) As Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TResult)
Public Shared Function Compile(Of TArg0 As DataContext, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TResult)(query As Expression(Of Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TResult))) As Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TResult)
Public Shared Function Compile(Of TArg0 As DataContext, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TResult)(query As Expression(Of Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TResult))) As Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TResult)
Public Shared Function Compile(Of TArg0 As DataContext, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TResult)(query As Expression(Of Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TResult))) As Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TResult)
Public Shared Function Compile(Of TArg0 As DataContext, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TResult)(query As Expression(Of Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TResult))) As Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TResult)
Public Shared Function Compile(Of TArg0 As DataContext, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TArg13, TResult)(query As Expression(Of Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TArg13, TResult))) As Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TArg13, TResult)
Public Shared Function Compile(Of TArg0 As DataContext, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TArg13, TArg14, TResult)(query As Expression(Of Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TArg13, TArg14, TResult))) As Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TArg13, TArg14, TResult)
Public Shared Function Compile(Of TArg0 As DataContext, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TArg13, TArg14, TArg15, TResult)(query As Expression(Of Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TArg13, TArg14, TArg15, TResult))) As Func(Of TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TArg13, TArg14, TArg15, TResult)
私はすぐに2つの問題があることを認識しました。一度は、Compile
メソッドは、異なる可能なパラメータ値と同じ数のパラメータを持つオーバーロードを返します。私が持っていた要素の数ごとにコンパイルされたクエリをキャッシュすることができるので、それほど深刻な問題ではありません。それはいくらかの記憶を無駄にするが、それほど多くはない。あまりにも多くなったら、私はレディスと一緒にそれを保管しますが、それは別の問題です。実際の問題は、パラメータの数が16を超えることはできず、私のList
は簡単に多くの要素を含むことができるということです。
,5,2,7,34,764,346,1,
このString
が含まれているかどうかを確認する:この問題に、解決策を開始し、そのセパレータで終わる、このたい各番号と文字列との間のセパレータと、String
にsumIDs
を変換することであろう与えられたtblFilterSum.SumID
は次のようにString
に変換:
"," & tblFilterSum.SumID & ","
が、これは仕事だろうが、インデックスを使用することはできません、それは非常に遅くなる文字列を比較します。私はこれらの問題があり、作業が緊急だったので、これをSQLで実装しましたが、LINQクエリをコンパイルして、任意の多くのパラメータをList
として渡すことができるかどうか疑問に思います。したがって、私の質問:
Listをパラメータとして使用してLINQクエリをコンパイルする方法はありますか?
編集:私はLINQのクリエイターに連絡する方法を知っていた場合は
、その後、私は答えを自分で見つけることができ信じています。私はGoogleでLINQを検索しましたが、残念ながら連絡先情報が見つかりませんでした。
フェリペは、あなたの答えをありがとう、しかし、あなたは質問を理解していないように見えます。 (残念ながら)私は.NET Framework 4.0を使用しているため、Entity Framework 5+は.NET 4.5+を依存関係として使用できません。自動キャッシュは、私のケースでは使用できないEntity Framework 5+の機能であるため、私たちが話している環境では自動キャッシュはまったく不可能です。自分の状況では自動キャッシュが不可能なので、私は手動キャッシュを行うつもりであり、Listで作業する必要があります。これが問題なのです。 –
私の場合は自動キャッシュができないので(.NET 4が含まれているタグからわかるように)、私は手動でキャッシュするつもりです(質問から分かるように)。問題はCompiledQuery.Compileがlistパラメータをサポートし、有限個の可能なパラメータを持ち、反射スタイルのパラメータが無駄になります。あなたは、自動コンパイルを可能にするためにカスタムに何かが含まれていることを示唆していますが、それは到達不能な機能です。 –
ああ、私はあなたがEF 5+を使うことができないことに気付かなかった。その質問にその旨のフレーズを追加することをお勧めします。私はあなたの問題を解決する方法がわかりません:( – felipe