有时候需要根据条件动态拼接查询逻辑,IQueryable 支持延迟执行——在调用 ToList()、First() 等之前,查询并不会真正发送到数据库。利用这个特性,可以分步构建查询,最终一次性执行。
代码示例
// 初始查询(此时未查库,只是定义查询结构)
var jfx = db.XX.AsQueryable();
// 根据条件动态拼接
if (isjq)
{
jfx = from j in jfx
join f in db.FY
on j.bh equals f.id
where f.lx == 0
select j;
}
// 后续继续使用 jfx 作为子表继续查询
var q = from jf in jfx
// ... 继续 where / join / select
select jf;
// 直到这里才真正执行 SQL
var result = q.ToList();Code language: JavaScript (javascript)
生成的 SQL(当 isjq = true 时)
SELECT [t0].[...]
FROM [dbo].[XX] AS [t0]
INNER JOIN [dbo].[FY] AS [t1]
ON [t0].[bh] = [t1].[id]
WHERE [t1].[lx] = 0Code language: PHP (php)
不带条件时的 SQL
当 isjq = false 时,jfx 没有被重新赋值,直接作为 XX 表的查询:
SELECT [t0].[...]
FROM [dbo].[XX] AS [t0]Code language: CSS (css)
常见用法模式
模式一:条件追加 Where
var q = db.Student.AsQueryable();
if (!string.IsNullOrEmpty(keyword))
{
q = q.Where(s => s.name.Contains(keyword));
}
if (minAge.HasValue)
{
q = q.Where(s => s.age >= minAge.Value);
}
var result = q.ToList();Code language: JavaScript (javascript)
模式二:条件 Join(你的示例)
var q = db.XX.AsQueryable();
if (isjq)
{
q = from j in q
join f in db.FY on j.bh equals f.id
where f.lx == 0
select j;
}Code language: JavaScript (javascript)
模式三:条件排序
if (sortBy == "age")
{
q = q.OrderBy(s => s.age);
}
else
{
q = q.OrderBy(s => s.name);
}Code language: JavaScript (javascript)
关键要点
| 要点 | 说明 |
|---|---|
| 延迟执行 | IQueryable 在 ToList()/First()/Count() 等终端方法调用前不查库 |
| 链式拼接 | 每次 Where/Join/OrderBy 返回新 IQueryable,需重新赋值 |
| 最终合并 | 所有拼接逻辑合并为一条 SQL 发给数据库 |
AsQueryable() | 将 Table<T> 显式转为 IQueryable<T>,方便后续赋值 |
| 性能 | 比先 ToList() 再在内存中过滤好得多,全程数据库端执行 |
注意: 不要对
IQueryable调用ToList()后再拼接条件,那会把全表数据拉到内存。始终保持IQueryable直到最后一步才物化。
Previous: 同一张表对应多个 DBML 类
Next: 分组后使用 into 保存分组结果