我一直使用这些常见的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);
}
答案 0 :(得分:3)
不,当qry
被输入为IEnumerable<T>
时,它会调用Enumerable.SingleOrDefault
而不是Queryable.SingleOrDefault
。 lambda表达式将转换为委托而不是表达式树,并且不会使用SQL。
请注意,SingleOrDefault
首先不使用延迟执行 - 它总是立即执行 - 但区别在于执行查询的位置。你几乎肯定希望数据库能够做到这一点。如果您查看带有简化版本的日志,您将看到 all 正在获取结果 - 而IQueryable<T>
重载时,SQL将包含相关的过滤。< / p>