Выражения Linq с Linq для сущностей - PullRequest
1 голос
/ 29 февраля 2012

Я пытаюсь обернуть некоторый повторяющийся код в метод расширения, чтобы немного очистить вещи.

Шаблон, который я стараюсь избегать, проверяет, является ли строка (обычно текстовое значение элемента управления) нулевой / пустой, и если это так, сравнивает ее с помощью Contains с полем в моих данных. Очевидно, что поле не жестко запрограммировано в моем расширении, равно как и тип объекта.

То, что у меня есть, прекрасно работает в Linq to Objects, но я получаю общую ошибку времени выполнения: «LINQ to Entities не распознает метод« System.String Invoke (GenericQueryHelper.Customer) », и этот метод не может перевести в магазинное выражение. при использовании модели структуры объекта.

Вот что у меня есть:

<System.Runtime.CompilerServices.Extension()>
Public Function CompareAndFilter(Of T)(source As System.Linq.IQueryable(Of T), expressionField As System.Linq.Expressions.Expression(Of System.Func(Of T, String)), compareTo As String)
    If String.IsNullOrEmpty(compareTo) Then
        Return source
    Else
        Dim compiledField As System.Func(Of T, String) = expressionField.Compile()
        Return source.Where(Function(x) compiledField.Invoke(x).Contains(compareTo))
    End If
End Function

И я тоже попробовал:

<System.Runtime.CompilerServices.Extension()>
Public Function CompareAndFilter(Of T)(source As System.Linq.IQueryable(Of T), expressionField As System.Func(Of T, String), compareTo As String)
    If String.IsNullOrEmpty(compareTo) Then
        Return source
    Else
        Return source.Where(Function(x) expressionField.Invoke(x).Contains(compareTo))
    End If
End Function

С идентичным исходом ...

Во-первых, это вообще возможно? Я хочу, чтобы мое использование выглядело примерно так:

Dim results = repository.Customers.CompareAndFilter(Function(c) c.FirstName, searchText)

Мне действительно нужно, чтобы это работало с базой данных SQL, поскольку она фильтрует результаты, поэтому я не хочу делать это в памяти. У кого-нибудь есть мысли?

Ответы [ 2 ]

3 голосов
/ 29 февраля 2012

Да, это возможно, но это включает в себя выражение манипулирование. Вы можете либо проанализировать заданное вами выражение и построить новое выражение критерия самостоятельно, либо LINQKit выполнить обход дерева.

2 голосов
/ 29 февраля 2012

Linq для сущностей не понимает, как вызывать делегата, ему нужно выражение для обработки SQL для генерации.

Следующее может быть в состоянии сделать то, что вы ищете:

<System.Runtime.CompilerServices.Extension()>
Public Function CompareAndFilter(Of T)(source As System.Linq.IQueryable(Of T), expressionField As System.Linq.Expressions.Expression(Of System.Func(Of T, String)), compareTo As String)
    If String.IsNullOrEmpty(compareTo) Then
        Return source
    Else
        Return source.GroupBy(expressionField)
            .Where(Function(g) g.Key.Contains(compareTo))
            .SelectMany(Function(g) g)
    End If
End Function

GroupBy используется для выбора поля, указанного expressionField, затем проверяется ключ и возвращаются элементы в каждой группе.

...