如果我使用IEnumerable <t>而不是IQueryable <t>进行过滤,我的Linq To Sql执行是否会延迟?</t> </t>

时间:2010-05-17 09:04:28

标签: linq-to-sql extension-methods ienumerable expression-trees iqueryable

我一直使用这些常见的EntityObjectFilters作为“管道和过滤器”方式从集合中查询具有ID的特定项目:

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>时,表达式树将传递给LinqToSql以作为SQL代码进行评估我的qry会先完整评估,然后用Func s进行迭代吗?

我怀疑(按照Richard's answer)后者将是真的,这显然是我不想要的。我想要相同的结果,但IQueryable<T>的延迟SQL执行的额外好处。有人可以向我确认实际会发生什么,并提供简单的解释,说明它将如何运作?

编辑:

解决方案我选择了

    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 个答案:

答案 0 :(得分:3)

不,当qry被输入为IEnumerable<T>时,它会调用Enumerable.SingleOrDefault而不是Queryable.SingleOrDefault。 lambda表达式将转换为委托而不是表达式树,并且不会使用SQL。

请注意,SingleOrDefault首先不使用延迟执行 - 它总是立即执行 - 但区别在于执行查询的位置。你几乎肯定希望数据库能够做到这一点。如果您查看带有简化版本的日志,您将看到 all 正在获取结果 - 而IQueryable<T>重载时,SQL将包含相关的过滤。< / p>