Вы должны понимать, что ваш запрос реализует IQueryable<...>
.
Объект, который реализует IQueryable
, имеет Expression
и Provider
.Expression
является общим представлением того, что должно быть запрошено.Provider
знает, кто должен выполнить запрос и на каком языке использует этот исполнитель.
Когда вы начинаете перечислять последовательность, которую представляет IQueryable
(= при вызове .ToList()
), Expression
отправлено на Provider
.Provider
переведет Expression
на язык, который понимает процесс, который должен выполнить запрос (обычно SQL), и отправит его исполняющему процессу.
Возвращенные данные помещаются в объект, который реализуетIEnumerable<...>
, и этот объект перечисляется.
Проблема в том, что поставщик знает только, как перевести довольно простой Expressions
в SQL.Он не знает, как перевести Func2
.
Я не вижу, чтобы вы использовали какой-либо элемент T3 в своем запросе.Это ошибка ввода?
В любом случае, самым простым решением было бы поместить код Func2 в Func1:
(я больше знаком с синтаксисом метода LINQ, чем с LINQ).синтаксис запроса, но вы получите суть)
см. Enumerable.Join
var result = dbContext.T1
// don't take all T1 items, but only the ones where:
.Where(t1 => t1.col2 > 300
&& t1.col3 != 1
&& t1.col4 != 285
&& t1.col5 != 830
&& t1.col6 > 0
// join the remaining t1s with table T3
.Join dbContext.T3,
t1 => t1.Id, // from every T1 take the id
t3 => t3.Id, // from every T3 take the id
// ResultSelector: take a t1 and a matching t3 to create one new object
(t1, t3) => new MyModel
{
Id = t1.Id,
// IsFunc2: true if Table2 has any element with Id equal to t1.Id and col values
IsFunc2 = dbContext.Table2
.Where(t2 => t2.ID == t1.Id
&& (t2.col1 > 0 || t2.col2 != "" || t2.col3 != ""))
.Any();
});
Если вы будете часто использовать Func2 в различных выражениях, вы можетерассмотрим преобразование Func2 таким образом, чтобы оно принимало IQueryable в качестве входных данных.
Я создал его как функцию расширения IQueryable<Table2Row>
.См. Расширение методов расширения:
static bool Func2(this IQueryable<Table2Row> rows, int id)
{
return rows
.Where(row => row.ID == id && (row.col1 > 0 || row.col2 != "" || row.col3 != ""))
.Any();
}
Теперь вы можете использовать его в ResultSelector соединения:
(t1, t3) => new MyModel
{
Id = t1.Id,
IsFunc2 = dbContext.Table2.Func2(t1.Id),
});