我有一个可以同时对IEnumerable
和IQueryable
进行操作的扩展方法。该方法解析输入并最终调用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
方法调用它(所以简单地换掉东西)是安全的。
答案 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); }
}
但我最终这样做只是因为我可以避免一个问题,这个问题会让我整整一个早上都在追逐一个上帝抛弃的虫子,最后面对死胡同而面对贴在墙上的留言“我告诉过你了”