Почему свойства навигации в linq для сущностей в подзапросе не реализуют IQueryable? - PullRequest
2 голосов
/ 08 мая 2011

Я недавно заметил нечто странное, свойства навигации в 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()));
        }
    }
}

1 Ответ

0 голосов
/ 08 мая 2011

Q1: Я тоже думаю, что это правильно.

Q2: Да, если вы передадите Func или любой делегат в выражение, компиляция запроса не удастся.Q3.

Но некоторое время назад у меня была похожая проблема во время игры в EF.И я обнаружил, что приведение этих реляционных свойств к IQueryable и вызов методов Expressions с удивительной эффективностью работает.Но это может быть случайность.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...