2012-03-13 15 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' 

所以,問題是如何結合LINQ-to-SQL將表達式委託給一個表達式,而不調用Invoke或AsQueryable,或者不會失去最佳執行。

+0

如果這是C#,我會嘗試替換所有使用'Func <>' 'Expression >',因爲編譯器可以將lambda翻譯成任意一個。這也是VB的真實嗎?你可以給一個'Expression(Of Func(Of whatever))'賦值一個內聯函數表達式嗎? – AakashM 2012-03-13 18:50:39

+0

是的,我想我嘗試過,但仍不知道如何調用表達式。您會注意到我提出的解決方案完全符合您的建議,但也找到了「調用」表達式(將它合併到Queryable的表達式樹中)的方法,這是我缺少的部分。 – BlueMonkMN 2012-03-13 19:15:54

回答

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我建議使用ToUpper而不是ToLower來在大小寫敏感的服務器上強制區分大小寫匹配,因爲我聽說UPPER更適合於此優化。)