返回IQueryable表达式而不执行数据库查询
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了返回IQueryable表达式而不执行数据库查询相关的知识,希望对你有一定的参考价值。
虽然对使用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不会调用数据库并执行该过程。
我的期望是这些db调用应该首先发生,因为我正在返回IQueryable。
到底是怎么回事?
答案
可组合查询的想法仅适用于基于表达式树的动态查询。如果你调用一个存储过程,你实际上是在调用一个存储过程 - 你必须添加.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};
其中两个单独的where
由order by
和列的子选择组成,以创建一个组合的SQL查询,如:
select Id, Name
from Customers
where Region = @p0 and Value > @p1
order by Name
以上是关于返回IQueryable表达式而不执行数据库查询的主要内容,如果未能解决你的问题,请参考以下文章
当我只需要计数而不读取 Document-Db 数据库中的所有文档时,如何使用 Linq 构造 IQueryable 查询?