2016-06-21 1 views
1

у меня есть два метода, которые возвращают IQueryable:Используя специальные методы, которые возвращают IQueryable в LINQ к объектам

IQueryable<Person> GetGoodPeople(); 

и

IQueryable<Person> GetBadPeople(); 

Мне нужно написать этот запрос:

var q = from x in GetGoodPeople() 
     from y in GetBadPeople() 
     select new { Good = x, Bad = y }; 

Вышеприведенный код не поддерживается в linq для сущностей (забрасывается NotSupportedException), за исключением того, что я объявляю повторно переменной и использовать его в запросе:

var bad = GetBadPeople() 
var q = from x in GetGoodPeople() 
     from y in bad 
     select new { Good = x, Bad = y }; 

Есть ли способ, что я могу использовать IQueryable методы в LINQ к лицам напрямую?

+2

Какая ошибка вы получаете во время исполнения? а также показать нам реализацию GetGoodPeople() – Prathyush

+0

Исключение: 'System.NotSupportedException LINQ to Entities не распознает метод 'System.Linq.IQueryable'1 [...] Метод запроса [...]() , и этот метод не может быть переведен в выражение хранилища. ' – Khodaie

+0

Вы пытались со свойствами: 'IQueryable GetGoodPeople {get; set;} ' – tschmit007

ответ

3

Короткий ответ - это не возможно возможно. Ваше исправление - это правильный способ решения проблемы.

После того, как структура объекта (и LINQ2Sql) начинает разбор дерева выражений, уже слишком поздно. Вызов GetBadPeople() фактически выполняется лениво и, как таковой, пытается быть преобразован в сам SQL .

Вот что это может выглядеть следующим образом:

Table(Person).Take(1).SelectMany(x => value(UserQuery).GetBadPeople(), (x, y) => new <>f__AnonymousType0`2(Good = x, Bad = y)) 

Вот, я написал GetGoodPeople() просто как возвращение People.Take(1). Обратите внимание, что этот запрос verbatim, но GetBadPeople() содержит вызов функции.

Ваше обходное решение для оценки GetBadPeople() вне выражения - правильное решение. Это приводит к тому, что дерево выражений вызывает Expression.Constant(bad), вместо того, чтобы ссылаться на вызов GetBadPeople().

Это делает внешний вид запроса, как это:

Table(Person).Take(1).SelectMany(x => value(UserQuery+<>c__DisplayClass1_0).bad, (x, y) => new <>f__AnonymousType0`2(Good = x, Bad = y)) 

Примечание нет никакого вызова метода здесь - мы просто передать в переменной.

+2

It's * возможно *, только ... не так же просто. Вам нужно будет преобразовать первое выражение во второе. Вы можете написать способ для этого. – Servy

+0

@Servy Вы правы, я был, возможно, слишком черно-белым с ответом (в том, что это не возможно *). На самом деле у меня есть решение для inline invokes [здесь] (http://stackoverflow.com/questions/34408179/linq-expression-calling-combines/34416123#34416123) - хотя при использовании свободного синтаксиса требуется немного больше работы – Rob

+0

, Я имел в виду синтаксис запроса – Rob

0

Вы можете приблизиться к декартовой продукции с помощью неограниченного соединения. Это не похоже на исключение NotSupportedException. Я проверил бэкэнд, и он отображает одно заявление sql.

var q = from x in GetGoodPeople() 
     join y in GetBadPeople() 
     on 1 equals 1 
     select new { Good = x, Bad = y }; 
+0

Проблема заключается в способе создания 'IQueryable' внутри запроса, поскольку поставщик запроса не знает, что делать с этим методом. Это никоим образом не затрагивает эту проблему. – Servy

+2

@Servy ... За исключением того факта, что Linq-to-entity интерпретирует соединение правильно, так же, как обходное решение OP для объявления переменной работает. Как это не решает проблему? – Derpy

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