Я решил свою проблему, но потому, что я пытался и не смог ее решить раньше, и на этот раз мне потребовалось немало усилий, я хотел опубликовать вопрос , и если никто не имеет лучшего ответа, мое решение, поэтому я не забываю, как это сделать в будущем, и помогать кому-либо другому сталкиваться с подобной проблемой. Моя задача заключается в следующем:Как объединить запросы 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-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'
Таким образом, вопрос в том, как объединить выражения делегата LINQ-to-SQL в одно без вызова Invoke или AsQueryable или без потери оптимального исполнения.
Если бы это был C#, я бы попытался заменить все использования 'Func <>' с 'Expression>', поскольку компилятор может перевести лямбда в любой. Это относится и к VB? Можете ли вы назначить выражение встроенной функции выражению 'Expression (Of Func (Of whatever))? –
AakashM
Да, я думаю, я пробовал это, но все еще не знал, как вызвать выражение. Вы заметите, что решение, которое я придумал, делает именно то, что вы предлагаете, но также находит способ «вызывать» выражение (объединить его в дерево выражений Queryable), которое было частью, которую я отсутствовал. – BlueMonkMN