强制 Entity Framework 6.1 使用 exists 而不是填充整个子对象图。
强制 Entity Framework 6.1 使用 exists 而不是填充整个子对象图。
返回 IQueryable
和 IEnumerable
有什么区别?什么时候应该优先选择其中一个?
IQueryable custs = from c in db.Customers where c.City == "" select c; IEnumerable custs = from c in db.Customers where c.City == "" select c;
两个都将是延迟执行的,什么时候应该优先选择其中一个?
顶部的回答很好,但它没有提到表达式树,表达式树解释了这两个接口的区别是如何的。基本上,LINQ扩展有两个完全相同的集合。 Where()
, Sum()
, Count()
, FirstOrDefault()
等都有两个版本:一个接受函数,一个接受表达式。
-
IEnumerable
版本签名为:Where(Func
predicate) -
IQueryable
版本签名为:Where(Expression
IPX。> predicate)
您可能一直在使用这两个版本而没有意识到,因为它们都使用相同的语法来调用:
例如:Where(x=>x.City ==“
适用于 < code> IEnumerable code>和 < code> IQueryable code>。
-
当在
IEnumerable code>集合上使用
Where() code>时,编译器将编译函数传递给< code> Where() code>
-
当在
IEnumerable code>集合上使用
Where() code>时,编译器会将表达式树传递给
Where() code>中。表达式树就像反射系统但适用于代码。编译器将您的代码转换为描述代码在易于消化的格式中执行的数据结构。
为什么要使用这个表达式树呢? 我只是想通过 Where() code>过滤我的数据。
主要原因是,EF和Linq2SQL ORM都可以将表达式树直接转换为SQL,其中您的代码将执行得更快。
哦,听起来像是一种免费的性能提升,那我在这种情况下应该在所有地方使用AsQueryable()
吗?
不,IQueryable
只有在底层数据提供程序可以对其进行处理时才有用。将类似于普通List
的东西转换为IQueryable
将不会给您带来任何好处。
是的,两者都会给你延迟执行。
区别在于,IQueryable
是允许LINQ-to-SQL(或LINQ-to-任何其他)工作的接口。因此,如果你在IQueryable
上进一步细化你的查询,如果可能的话,该查询将在数据库中执行。
对于IEnumerable
的情况,它将是LINQ-to-object,这意味着必须从数据库中将与原始查询匹配的所有对象加载到内存中。
在代码中:
IQueryablecusts = ...; // Later on... var goldCustomers = custs.Where(c => c.IsGold);
这段代码将只执行SQL以选择金色客户。另一方面,以下代码将在数据库中执行原始查询,然后在内存中过滤掉非金色客户:
IEnumerablecusts = ...; // Later on... var goldCustomers = custs.Where(c => c.IsGold);
这是一个非常重要的区别,在IQueryable
上工作可以在许多情况下避免从数据库返回过多的行。另一个最好的例子是分页:如果在IQueryable
上使用Take
和Skip
,你将只得到所请求的行数。在IEnumerable
上做这个操作将导致将所有行加载到内存中。