返回IEnumerable和IQueryable的区别

19 浏览
0 Comments

返回IEnumerable和IQueryable的区别

在返回 IQueryableIEnumerable 时有什么区别?应该在什么情况下优先选择其中一个?

IQueryable custs = from c in db.Customers
where c.City == ""
select c;
IEnumerable custs = from c in db.Customers
where c.City == ""
select c;

两者都是延迟执行的,但应该在什么情况下更倾向于使用其中一个?

admin 更改状态以发布 2023年5月24日
0
0 Comments

顶部答案很好,但它没有提到表达式树,这解释了这两个接口的“如何”不同。基本上,有两组相同的LINQ扩展。`Where()`,`Sum()`,`Count()`,`FirstOrDefault()`等都有两个版本:一个接受函数,另一个接受表达式。

- `IEnumerable`版本签名是:`Where(Func predicate)`
- `IQueryable`版本签名是:`Where(Expression> predicate)`

您可能一直在使用这两种方式而没有意识到,因为两者都使用相同的语法进行调用:

例如,`Where(x => x.City == "")`适用于`IEnumerable`和`IQueryable`

在`IEnumerable`集合上使用`Where()`时,编译器将编译的函数传递给`Where()`。

当在`IQueryable`集合上使用`Where()`时,编译器将表达式树传递给`Where()`。表达式树就像反射系统,但用于代码。编译器将您的代码转换为数据结构,该数据结构以易于消化的格式描述您的代码执行的操作。

为什么要麻烦这个表达式树?我只想要`Where()`来筛选我的数据。

主要原因是EF和Linq2SQL ORM均可以将表达式树直接转换为SQL,其中您的代码将更快地执行。哦,那听起来像是一个免费的性能提升,那我应该在这种情况下到处使用AsQueryable() 吗? 不,IQueryable 只有在底层数据提供程序可以处理它时才有用。将像常规的List这样的东西转换为IQueryable 不会给您带来任何好处。

0
0 Comments

是的,两者都会给你延迟执行

区别在于IQueryable是允许LINQ-to-SQL(实际上是LINQ-to-anything)工作的接口。因此,如果你在IQueryable上进一步细化你的查询,那么如果可能的话,该查询将在数据库中执行。

对于IEnumerable,它将是LINQ-to-object,这意味着该原始查询的所有匹配对象都必须从数据库加载到内存中。

在代码中:

IQueryable custs = ...;
// Later on...
var goldCustomers = custs.Where(c => c.IsGold);

该代码将只执行SQL以选择黄金客户。另一方面,下面的代码将在数据库中执行原始查询,然后在内存中过滤掉非黄金客户:

IEnumerable custs = ...;
// Later on...
var goldCustomers = custs.Where(c => c.IsGold);

这是一个相当重要的区别,使用IQueryable在许多情况下可以防止从数据库返回过多的行。另一个主要例子是进行分页:如果你在IQueryable上使用TakeSkip,你只会得到所请求的行数;如果在IEnumerable上执行,会导致所有行都在内存中加载。

0