返回IQueryable表达式而不执行数据库查询

问题描述 投票:2回答:1

虽然对使用IQueryable希望改善现有代码性能感到好奇,但我遇到了这个online test case

为了测试所提出的例子的有效性,我:

  • 创建了两个存储过程
  • 称他们如下: static void Main(string[] args) { GetCustomers(); GetRules(); } public static IQueryable GetCustomers() { var db = new DbEntities(); return db.GetCustomers().AsQueryable(); } public static IQueryable GetRules() { var db = new DbEntities(); return db.GetRules(null).AsQueryable(); }
  • 跟踪SQL Server Profiler中的db调用

根据链接中提供的示例测试问题

因此,我们对数据库执行单个复杂查询(当调用.ToList()时),而不是分别检索两个集合并将它们连接到服务器端。

我明白只要我们返回IQueryable,就不会启动db调用,直到.ToList()被调用。

但是,在我提供的代码示例中:

  • GetRules始终调用db并执行过程,无论调用方法的顺序如何,在GetCustomers之前或之后
  • 在控制台应用程序准备退出之前,GetCustomers不会调用数据库并执行该过程。

enter image description here

我的期望是这些db调用应该首先发生,因为我正在返回IQueryable。

到底是怎么回事?

c# entity-framework linq stored-procedures iqueryable
1个回答
3
投票

可组合查询的想法仅适用于基于表达式树的动态查询。如果你调用一个存储过程,你实际上是在调用一个存储过程 - 你必须添加.AsQueryable()的事实通常意味着你实际上在一个完全物化的对象上使用LINQ-to-Objects(例如List<Customer>或类似的) ,但只是将其描述为可查询。那时候:为时已晚 - 你已经执行了它。

有可能以某种方式组合存储过程,但我不会依赖它。当人们谈论IQueryable<T>时,这并不是真正的目标场景。而是用于以下事项:

IQueryable<Customer> CustomersByRegion(string region)
   => db.Customers.Where(c => c.Region == region);
...
var data = from cust in CustomersByRegion("North")
           where cust.Value > 10000
           order by cust.Name
           select new {cust.Id, cust.Name};

其中两个单独的whereorder by和列的子选择组成,以创建一个组合的SQL查询,如:

select Id, Name
from Customers
where Region = @p0 and Value > @p1
order by Name
© www.soinside.com 2019 - 2024. All rights reserved.