链接AsEnumerable和AsQueryable是否安全
本文关键字:是否 安全 AsQueryable AsEnumerable 链接 | 更新日期: 2023-09-27 18:27:15
我有一个扩展方法,可以对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
方法调用它(所以只是简单地切换)是安全的。
否;这不是一个好主意。
调用AsEnumerable()
将实现整个查询,然后在客户端上运行Skip()
和Take()
。
您需要制作一个单独的(相同的)方法版本,该版本接受并返回仅调用Queryable方法的IQueryable<T>
,以便查询可以在服务器上运行。
简短的答案:也许
AsEnumerable()
可能会实现您的查询。最简单的方法是获取SQL Server Express Profiler并并行调试,以查看查询何时被调用。实际上,IQueryable
继承自IEnumerable
。
此外,在调试时:如果你想看看发生了什么,IDE可能会将其具体化,并在漂亮的VS浮动GUI调试工具中显示出来
根据我的经验:从AsEnumerable()
到AsQueryable()
的来回跳跃直到我调用ToArray()
、ToList()
或任何其他从ICollection
继承的东西才实现,但请记住,IQueryable
在内存中保持类似于Graph的计算。因此,即使您实际上没有看到它在数据库中进行查询,在内存较低的情况下,您可能会看到一些性能成本。
和你一样,我试图避免在存储库模式中生成重复数据,特别是在分页时:
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); }
}
但我最终这样做是为了避免出现一个问题,这个问题会让我整个上午都在追逐一只被上帝遗弃的虫子,最终陷入死胡同,我会面对墙上贴着的一张纸条,上面写着"我早就告诉过你了"