【问题标题】:Will my LinqToSql execution be deffered if i filter with IEnumerable<T> instead of IQueryable<T>?如果我使用 IEnumerable<T> 而不是 IQueryable<T> 进行过滤,我的 Linq To Sql 执行会被推迟吗?
【发布时间】:2011-02-20 07:46:24
【问题描述】:

我一直使用这些常见的 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&lt;T&gt; 类型创建一个扩展来简化这个吗?
所以我想出了这个:

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&lt;T&gt;s 时,表达式树是否会被传递给 LinqToSql 以作为 SQL 代码进行评估或 我的qry 会先被完整地评估,然后用Funcs 迭代吗?

我怀疑(根据Richard's answer)后者将是真的,这显然是我不想要的。我想要相同的结果,但延迟 SQL 执行对IQueryable&lt;T&gt;s 的额外好处。有人可以为我确认实际会发生什么并提供简单的解释来说明它是如何工作的吗?

编辑:

我采用的解决方案

    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);
    }

【问题讨论】:

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


    【解决方案1】:

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

    请注意,SingleOrDefault 首先不使用延迟执行 - 它总是立即执行 - 但不同之处在于执行查询的位置。您几乎可以肯定希望数据库来执行此操作。如果您使用简化版本查看日志,您会看到所有结果正在被获取 - 而IQueryable&lt;T&gt; 重载,SQL 将包含相关过滤。

    【讨论】:

    • 您是说在第一个示例的第一个函数中,SingleOrDefault 甚至不会使用 SQL WHERE
    • 是的,这正是 Jon 的意思。这样做可能会从表中检索所有数据行并过滤客户端。这对性能非常不利。
    • 等一下:他说SingleOrDefault 不使用延迟执行,但如果是Queryable.SingleOrDefault,它可以在SQL 中查询。这似乎表明第一个示例中的第一个函数将使用 SQL WHERE。同意吗?
    • @cottsak:第一个函数应该在 SQL 中使用 WHERE,是的。使用您的第二个 sn-p,超过 IEnumerable&lt;T&gt; 不会使用 WHERE。
    • @Jon:参考编辑:这是满足单一扩展方法要求的可接受折衷方案吗?
    猜你喜欢
    • 1970-01-01
    • 2012-06-23
    • 1970-01-01
    • 1970-01-01
    • 2010-09-07
    • 2011-03-03
    • 2011-03-04
    相关资源
    最近更新 更多