Я недавно заметил нечто странное, свойства навигации в Entitiy не реализуют IQueryable,
хотя, насколько мне известно, получение одной сущности с последующим объединением операторов в свойства навигации может привести к множеству (1 на элемент) обращений к базе данных, из сгенерированного кода, который я видел, есть один большой запрос с результатами подзапросов (когда это возможно) в одном большом запросе.
Однако мне интересно, как это работает, потому что перегрузки, доступные в подзапросе, такие же, как те, которые будут вызываться для свойства навигации вне подзапроса.
Вопрос 1: я предполагаю, что, даже если он выполняется в IEnuerable, а сам вызов any является частью выражения, передаваемого куда, он затем встраивается в единственное дерево выражений, генерируемое в where и анализируемое там, а не как отдельное выражение (так как это не выражение само по себе), это правильно?
Вопрос 2: Если # 1 верно, как это работает, если вы создаете код вне выражения, который может быть сделан только в делегате во время выполнения (например, как это будет работать, если я передал PredicateExprEntityTwo.Compile () в q5 это не скомпилируется и не завершится во время выполнения, потому что компилятор не знает об использовании функции внутри выражения во время компиляции?
Вопрос 3: Предполагая, что у меня есть правильные # 1 и # 2, в чем преимущество этого дизайна по сравнению с принятием там выражения? Недостаток, с которым я столкнулся, заключается в том, что для проверки бизнеса я думал о том, чтобы иметь набор предикатов со встроенной в них бизнес-логикой для фильтрации объектов одного типа во многих местах в программе, однако я могу использовать их в подзапросах. и если предположить, что № 2 прав, возможно, будет невозможно повторно использовать тот же?
Извините, если вопросы звучат немного запутанно, но я только заметил на прошлой неделе, что у меня была вызвана перегрузка IEnumerables в подзапросах, но все еще один EF-запрос в качестве вывода, и мне очень любопытно, как это может работать .
public class Class1
{
void Test()
{
Func<Entity1, bool> PredicateFuncEntityOne = i => i.Id == 2;
Expression<Func<Entity1, bool>> PredicateExprEntityOne = i => i.Id == 2;
Func<Entity2, bool> PredicateFuncEntityTwo = i => i.Id == 2;
Expression<Func<Entity2, bool>> PredicateExprEntityTwo = i => i.Id == 2;
using (var Context = new TestModelContainer())
{
// Works as this expects an expression
var q1 = Context.Entity1Set.Where(PredicateExprEntityOne);
// Works but would call the IEnumerable version
var q2 = Context.Entity1Set.Where(PredicateFuncEntityOne);
// This compiles, any on item.Entity2 expects a func on IEnumerable, not IQueryable overload
var q3 = Context.Entity1Set.Where(item => item.Entity2.Any(PredicateFuncEntityTwo));
// This fails for the reason mentioned above
var q4 = Context.Entity1Set.Where(item => item.Entity2.Any(PredicateExprEntityTwo));
// Does this work and if so how is it possible?
var q5 = Context.Entity1Set.Where(item => item.Entity2.Any(PredicateExprEntityTwo.Compile()));
}
}
}