LINQ — динамическое предложение Where в синтаксисе запроса

Я искал, как делать динамические запросы, и все, что я нашел, использовало «Синтаксис метода».

Можно ли создавать динамические предикаты для "Синтаксиса запроса"?

Я пытался использовать что-то вроде

Expression<Func<TEntity, bool>>

внутри предиката, но компилятор возвращает следующее сообщение

"Cannot convert Expression<Func<TEntity, bool>> to bool"

он работает с «Синтаксис метода», но не с «Синтаксис запроса»

Оно работает:

Expression<Func<Localization, bool>> locClause = (l => l.id == locId);

var results = UnitOfWork.Localization.AsQueryable().Where(locClause).ToList();

Это не работает:

Expression<Func<Localization, bool>> locClause = (l => l.id == locId);

var result = from l in UnitOfWork.Localization.AsQueryable()
                          where locClause 
                          select l;

Есть ли способ сделать это ?


person vdefeo    schedule 24.09.2014    source источник
comment
Выражение не может быть передано в подсистему LINQ в синтаксисе запроса и обработано во время выполнения, вы должны иметь дело с ним во время компиляции (т.е. скомпилировать его). Но было бы проще просто использовать Func (или Predicate) и сделать where locClause(l)   -  person Peter Ritchie    schedule 24.09.2014
comment
Можете ли вы привести мне пример?   -  person vdefeo    schedule 24.09.2014


Ответы (2)


Не зная, для чего вам нужен Expression, я не могу быть уверен, что он сделает все, что вам нужно. Использование AsQueryable заставило меня подозревать, что вы этого не сделаете (если вы напрямую запрашиваете провайдера, вы уже должны быть IQueryable<Localization>); но вам придется подтвердить. Но если вам нужно использовать Expression, вы можете сделать что-то вроде этого:

Func<Localization, bool> locClause = (l => l.id == locId);

var result = from l in UnitOfWork.Localization.AsQueryable()
                          where locClause(l)
                          select l;

Или с Predicate<T>:

Predicate<Localization> locClause = l => l.id == locId;

var result = from l in UnitOfWork.Localization.AsQueryable()
                          where locClause(l)
                          select l;

Это, конечно, означает, что делегат выполняется на клиенте, а не транслируется во что-то, выполняемое на сервере (то есть часть T-SQL, сгенерированного провайдером, если это действительно происходит сейчас). Если вам это нужно, вам нужно продолжать использовать Expression и продолжать использовать синтаксис цепочки методов:

var result = UnitOfWork.Localization.AsQueryable().Where(locClause);

Я не верю, что есть какая-то причина выбирать Predicate<T> вместо Func<T,bool>, кроме того, что Predicate<T> является более явным, чем Predicate<T>. к намерению.

Также нет функциональной выгоды от использования синтаксиса запроса по сравнению с синтаксисом цепочки методов — только удобство чтения/сопровождения. Я часто обнаруживаю, что выполнение чего-то сложного с поставщиками обычно приводит к тому, что синтаксис цепочки методов сводится к цепочке методов. Обычно я просто использую синтаксис запроса с LINQ To Objects.

person Peter Ritchie    schedule 24.09.2014

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

person Servy    schedule 24.09.2014
comment
Действительно ? Значит, нет возможности делать динамические запросы с синтаксисом запросов? - person vdefeo; 24.09.2014
comment
@ViniciusDefeo Не динамичны в том смысле, как вы пытаетесь их использовать, нет. - person Servy; 24.09.2014