Будет ли мое выполнение LinqToSql отложено, если я отфильтрую с IEnumerable <T>вместо IQueryable <T>? - PullRequest
0 голосов
/ 17 мая 2010

Я использовал эти распространенные EntityObjectFilters как способ «труб и фильтров» для запроса из коллекции определенного элемента с идентификатором:

public static class EntityObjectFilters
{
    public static T WithID<T>(this IQueryable<T> qry,
       int ID) where T : IEntityObject
    {
        return qry.SingleOrDefault<T>(item => item.ID == ID);
    }

    public static T WithID<T>(this IList<T> list,
        int ID) where T : IEntityObject
    {
        return list.SingleOrDefault<T>(item => item.ID == ID);
    }
}

.. но я удивился: «Могу ли я сделать это проще, просто создав расширение для всех IEnumerable<T> типов»?
Итак, я придумал это:

public static class EntityObjectFilters
{
    public static T WithID<T>(this IEnumerable<T> qry,
       int ID) where T : IEntityObject
    {
        return qry.SingleOrDefault<T>(item => item.ID == ID);
    }
}

Теперь, когда этот появляется для получения того же результата, я хочу знать, что при применении к IQueryable<T> s дерево выражений будет передано в LinqToSql для оценки в виде кода SQL или будет ли мой qry сначала оцениваться целиком, а затем повторяться с Func s?

Я подозреваю, что (согласно ответу Ричарда ) последнее будет правдой, что, очевидно, является тем, чего я не хочу. Я хочу тот же результат, но дополнительное преимущество отложенного выполнения SQL для IQueryable<T> с. Может ли кто-нибудь подтвердить для меня, что на самом деле произойдет, и дать простое объяснение того, как это будет работать?

РЕДАКТИРОВАТЬ:

Решение, с которым я пошел

    public static T WithID<T>(this IEnumerable<T> qry,
        int ID) where T : DomainBase
    {
        if (qry is IQueryable<T>)
            return ((IQueryable<T>)qry).SingleOrDefault<T>(item => item.ID == ID);
        else
            return qry.SingleOrDefault<T>(item => item.ID == ID);
    }

1 Ответ

3 голосов
/ 17 мая 2010

Нет, когда qry набрано как IEnumerable<T>, оно будет вызывать Enumerable.SingleOrDefault, а не Queryable.SingleOrDefault. Лямбда-выражение будет преобразовано в делегат вместо дерева выражений и не будет использовать SQL.

Обратите внимание, что SingleOrDefault в первую очередь не использует отложенное выполнение - оно всегда немедленное - но разница в том, где выполняется запрос. Вы почти наверняка хотите, чтобы база данных сделала это. Если вы посмотрите журналы в упрощенной версии, вы увидите, что все результаты извлекаются - тогда как при перегрузке IQueryable<T> SQL будет содержать соответствующую фильтрацию.

...