1

У меня есть таблицы запросов, что имеет Сертификаты:EF запрос с использованием метода расширения внутри метода расширения

public class Request { 
    public virtual List<Approval> Approvals { get; set; } 
} 

Запросы поступают из БД

public DbSet<Request> Request { get; set; } 

у меня есть метод расширения:

public static IQueryable<Request> HaveApprovals(this IQueryable<Request> requests) { 
    return requests.Where(r => r.ActiveApprovals().Count() > 0).ToList(); 
} 

И еще один способ расширения:

public static IEnumerable<Approval> ActiveApprovals(this Request request) { 
    return request.Approvals.Where(a => !a.Deleted); 
} 

Но получить сообщение об ошибке:

LINQ to Entities does not recognize the method 'System.Collections.Generic.IEnumerable`1[Domain.Approval] ActiveApprovals(Domain.Request)' method, and this method cannot be translated into a store expression. 

По какой-то причине один метод расширения способен перевести на LINQ, но при использовании метода расширения внутри другого, то он не может перевести. Какие-либо предложения?

+0

Вы должны возвращать IQueryable со второго, а также –

+0

Я бы мог, если бы мог, но 'request.Approvals' - это' List', а using Where возвращает 'IEnumerable'. – Jaanus

ответ

0

Попробуйте переписать расширение HaveApprovals таким образом:

public static IQueryable<Request> HaveApprovals(this IQueryable<Request> requests) { 
    return requests.Where(r => r.Approvals.Any(a => !a.Deleted)).ToList(); 
} 

Ошибка происходит потому, что EF пытается выполнить любую операцию в запросе на стороне сервера (SQL Server). Поэтому SQL ничего не знает о вашем методе расширения и о том, как его выполнить.

UPDATE # 1:

запрос ниже

var query = this.DataContext.Products.Where(x => x.Sales.Any(s => s.SectorId == 1)); 

будет генерировать следующий SQL запрос

SELECT [t0].[Id], [t0].[Name], [t0].[Description] 
FROM [dbo].[Products] AS [t0] 
WHERE EXISTS(
    SELECT NULL AS [EMPTY] 
    FROM [dbo].[Sales] AS [t1] 
    WHERE ([t1].[SectorId] = @p0) AND ([t1].[ProductId] = [t0].[Id]) 
    ) 
} 

Это не извлечет все записи, так что не снижает производительность.

+0

Я хочу, чтобы он выполнялся в запросе, иначе он будет загружать мои 100 тыс. Элементов из базы данных и очень медленно. Он должен иметь возможность переводить контент метода расширения в LINQ, так же, как он работает при использовании только одного метода расширения, а не вложенного. – Jaanus

+0

Я обновил свой ответ с некоторыми доказательствами. Запрос не будет извлекать ваши 100 тыс. Элементов (см. Аналогичный запрос и сгенерированный SQL-запрос). Также нет способа перевести пользовательские методы расширения в SQL. – akorenchikov

+0

Проверьте этот раздел, чтобы увидеть, что при использовании IEnumerable он выполнит весь запрос, и фильтрация будет выполнена в памяти. http://stackoverflow.com/questions/2876616/returning-ienumerablet-vs-iqueryablet – Jaanus

Смежные вопросы