2012-03-13 8 views
3

私は自分の問題を解決しましたが、これまでに解決しようとしていたため、これを解決するのに時間がかかりました。誰もより良い答えを持っていなければ、私の解決策で、私はこれを将来どのように行うのか、誰かが同様の課題に直面するのを忘れることはありません。LINQ-to-SQLクエリを最適にマージする方法

Private Shared Function FilterResultsLot(ByVal source As IQueryable(Of Item), _ 
    ByVal itemCode As String) As IQueryable(Of Item) 
    If HasFilter(itemCode, True) Then 
     Return From row In source Where row.ItemDetail.IsLotTraced AndAlso _ 
       row.ItemCode.ToLower() Like itemCode.ToLower() 
    Else 
     Return From row In source Where row.ItemDetail.IsLotTraced 
    End If 
    End Function 

:私はたくさんのも、指定したパターンに一致するのみを表示する項目をトレースし、かつ、適用されているものだけを返すために、オプションのリストをフィルタリングするために使用される機能を持っている

:私の挑戦はこれです別の要件が上がってきた私は、一般的なフィルタの中にたくさんにトレースされた基準を一般化できるようにしたかったので、私は、この関数を作成しました:

Private Shared Function FilterResults(source As IQueryable(Of Item), _ 
    itemCode As String, filter As Func(Of Item, Boolean)) As IQueryable(Of Item) 
    Dim predicate As Func(Of Item, Boolean) 
    If HasFilter(itemCode, True) Then 
     predicate = Function(row) row.ItemCode.ToLower() Like itemCode.ToLower() AndAlso filter.Invoke(row) 
    Else 
     predicate = filter 
    End If 
    Return source.Where(predicate).AsQueryable() 
    End Function 

をその関数は、LINQツーSQLを介して動作しますが、それは重要な最適化を失います。最初の関数は、で終わるSQLクエリを実行しますに対し:

FROM [dbo].[OITM] AS [t0] 
LEFT OUTER JOIN [dbo].[FSE_ItemDetail] AS [t1] ON [t1].[ItemCode] = [t0].[ItemCode] 
WHERE ([t1].[IsLotTraced] = 1) AND (LOWER([t0].[ItemCode]) LIKE @p0 ESCAPE ''~'') 

第二は、これらの終末(および潜在的に、より多くの)と、複数のSQLクエリを実行します:

FROM [dbo].[OITM] AS [t0] 

FROM [dbo].[FSE_ItemDetail] AS [t0] 
WHERE [t0].[ItemCode] = @p0',N'@p0 nvarchar(4000)',@p0=N'BF-BIKE' 

FROM [dbo].[FSE_ItemDetail] AS [t0] 
WHERE [t0].[ItemCode] = @p0',N'@p0 nvarchar(4000)',@p0=N'BF-BIKE-ITEM' 

そこで問題は、どのように組み合わせるかでありますInvokeまたはAsQueryableを呼び出さずに、または最適な実行を失うことなく、LINQ-to-SQLデリゲート式を1つにデリゲートします。

+0

これはC#の場合、コンパイラはラムダをどちらかに変換することができるので、 'Expression 'でコンパイルできます。これはVBにも当てはまりますか?インライン関数式を 'Expression(Of Func(Of whatever))'に割り当てることができますか? – AakashM

+0

はい、私はそれを試みたと思うが、まだ表現を呼び出す方法を知らなかった。私が思いついた解決策は、あなたが提案したものとまったく同じですが、式を "呼び出す"方法(Queryableの式ツリーにマージする方法)があります。これは欠けていた部分でした。 – BlueMonkMN

答えて

1

ここに私の現在の解決策があります。コメントまたはあなたが持っている場合は、より良いソリューションを提供してくださいいかなる:

Private Shared Function FilterResults(source As IQueryable(Of Item), itemCode As String, filter As Expressions.Expression(Of Func(Of Item, Boolean))) As IQueryable(Of Item) 
    If HasFilter(itemCode, True) Then 
     Return Queryable.Where(Queryable.Where(source, Function(row) row.ItemCode.ToLower() Like itemCode.ToLower()), filter) 
    Else 
     Return Queryable.Where(source, filter) 
    End If 
    End Function 

編集:

もう少しそれで働いた後、私はこの構文を簡素化/代替を好む:

Return Queryable.Where(Queryable.Where(source, _ 
    Function(row) row.ItemCode.ToLower() Like itemCode.ToLower()), filter) 

私の好みは:

Return Queryable.Where(From row in source _ 
    Where row.ItemCode.ToUpper() Like itemCode.ToUpper(), filter) 

(I a lsoはToLowerの代わりにToLowerを提案して、大文字小文字を区別するサーバで大文字と小文字を区別しない一致を強制します。これはUPPERがより最適化されていると聞いたからです)。

関連する問題