我已经解决了我的问题,但是因为我之前已经尝试过但未能解决它,这次我花了很多功夫,我想发布问题,如果没有人有更好的答案,我的解决方案所以我不会忘记将来如何做到这一点,并帮助其他人面临类似的挑战。我的挑战是:
我有一个函数用于过滤选项列表,只返回批量跟踪的选项,并且在适用的情况下,也只显示与指定模式匹配的项目:
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-to-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委托表达式组合成一个,或者不失去最佳执行。
答案 0 :(得分: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)
(我还建议ToUpper而不是ToLower在区分大小写的服务器上强制不区分大小写的匹配,因为我听说UPPER更适合于此。)