链接AsEnumerable和AsQueryable是否安全?

时间:2013-08-12 11:46:00

标签: c#

我有一个可以同时对IEnumerableIQueryable进行操作的扩展方法。该方法解析输入并最终调用Skip().Take()

public static IEnumerable<T> SelectRange<T>(
    this IEnumerable<T> target,
    RangeHeaderValue range
    )

此方法适用于IQueryable,但会返回IEnumerable。所以我添加了另一种方法来转换,调用第一种方法并再次转换:

public static IQueryable<T> SelectRange<T>(
    this IQueryable<T> target,
    RangeHeaderValue range
    )
{
    return target.AsEnumerable().SelectRange(range).AsQueryable();
}

这样的链转换是否安全?我担心它会干扰IQueryable提供程序,而是在内存集合中运行该方法。我理解懒惰/急切加载的基础知识,但这是一个非常复杂的主题,我不想假设它会起作用。


注意:接受的答案对于链接的危险性是正确的,但我想补充说明实施IQueryable方法并从IEnumerable方法调用它(所以简单地换掉东西)是安全的。

2 个答案:

答案 0 :(得分:8)

没有;这不是一个好主意。

调用AsEnumerable()将实现整个查询,然后在客户端上运行Skip()Take()

您需要创建一个单独的(并且相同)版本的方法,并且只返回IQueryable<T>,它只调用Queryable方法,以便查询可以在服务器上运行。

答案 1 :(得分:1)

答案简短:也许

AsEnumerable() 可能实现您的查询。找出答案的最简单方法是并排查看SQL Server Express Profiler并进行调试,以查看调用查询的时间。实际上,IQueryable继承自IEnumerable

此外,在调试时:如果你试图看看发生了什么,IDE可能会实现它以在漂亮的VS浮动GUI调试工具中显示它

根据我的经验:在我调用AsEnumerable()AsQueryable()或任何继承自ToArray()的其他内容之前,从ToList()来回跳转到ICollection并未实现。 {1}},但请记住,IQueryable保持计算内存类似于图表。因此,即使您实际上没有看到它对DataBase进行查询,但在内存较低的情况下,您可能会考虑一些性能成本。

与您相同,我试图避免在存储库模式中生成重复,特别是在分页时:

public static class Paginate
{
    public static IEnumerable<T> Enumerable<T>(int records, int iPage, IEnumerable<T> input) where T : class { return input.Skip(records * iPage).Take(records); }

// My internal OCD hates this dup >.o
    public static IQueryable <T> Queryable <T>(int records, int iPage, IQueryable <T> input) where T : class { return input.Skip(records * iPage).Take(records); }
}

但我最终这样做只是因为我可以避免一个问题,这个问题会让我整整一个早上都在追逐一个上帝抛弃的虫子,最后面对死胡同而面对贴在墙上的留言“我告诉过你了”