返回IEnumerable <T>与IQueryable <T>

返回IQueryable<T>IEnumerable<T>什么区别?

IQueryable<Customer> custs = from c in db.Customers
where c.City == "<City>"
select c;

IEnumerable<Customer> custs = from c in db.Customers
where c.City == "<City>"
select c;

双方都会被推迟执行,并且什么时候应该比另一方优先?


是的,两者都会让你延期执行。

不同之处在于IQueryable<T>是允许LINQ到SQL(LINQ到任何事情)的接口。 因此,如果您进一步优化对IQueryable<T>查询,那么将尽可能在数据库中执行该查询。

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

在代码中:

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

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

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

这是一个非常重要的区别,使用IQueryable<T>在很多情况下可以使您免于从数据库中返回太多行。 另一个主要的例子是分页:如果你在IQueryable上使用TakeSkip ,你只会得到请求的行数; 在IEnumerable<T>上这样做会导致你所有的行都被加载到内存中。


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

  • IEnumerable版本签名是: Where(Func<Customer, bool> predicate)

  • IQueryable版本签名是: Where(Expression<Func<Customer, bool>> predicate)

  • 你可能一直在使用这两种方法而没有意识到它,因为两者都使用相同的语法来调用:

    例如, Where(x => x.City == "<City>")IEnumerableIQueryable

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

  • IQueryable集合上使用Where()时,编译器将表达式树传递给Where() 。 表达式树就像反射系统,但代码。 编译器将你的代码转换成一个数据结构,用一种易于理解的格式来描述你的代码的功能。

  • 为什么要打扰这个表达树的东西? 我只想要Where()来过滤我的数据。 主要原因是EF和Linq2SQL ORM都可以将表达式树直接转换为SQL,其代码执行速度会更快。

    噢,这听起来像是一个免费的性能提升,在这种情况下,我应该使用AsQueryable()吗? 不, IQueryable只有在底层数据提供者可以对它做些什么时才有用。 将常规List转换为IQueryable不会带来任何好处。


    是的,两者都使用延期执行。 让我们来说明使用SQL Server分析器的区别....

    当我们运行下面的代码时:

    MarketDevEntities db = new MarketDevEntities();
    
    IEnumerable<WebLog> first = db.WebLogs;
    var second = first.Where(c => c.DurationSeconds > 10);
    var third = second.Where(c => c.WebLogID > 100);
    var result = third.Where(c => c.EmailAddress.Length > 11);
    
    Console.Write(result.First().UserName);
    

    在SQL Server分析器中,我们发现一条命令等于:

    "SELECT * FROM [dbo].[WebLog]"
    

    对于拥有100万条记录的WebLog表,运行该代码块大约需要90秒。

    所以,所有的表记录都作为对象加载到内存中,然后与每个.Where()一起作为内存中另一个针对这些对象的过滤器。

    当我们在上面的例子(第二行)中使用IQueryable而不是IEnumerable时:

    在SQL Server分析器中,我们发现一条命令等于:

    "SELECT TOP 1 * FROM [dbo].[WebLog] WHERE [DurationSeconds] > 10 AND [WebLogID] > 100 AND LEN([EmailAddress]) > 11"
    

    使用IQueryable运行这段代码大约需要4秒钟的时间。

    IQueryable有一个名为Expression的属性,它存储了一个树形表达式,当我们在我们的示例中使用result (称为延迟执行)时,该表达式将开始创建,最后,该表达式将转换为SQL查询以在数据库引擎上运行。

    链接地址: http://www.djcxy.com/p/3621.html

    上一篇: Returning IEnumerable<T> vs. IQueryable<T>

    下一篇: define() vs const