LiteOrm在线文档

查询指南

LiteOrm 支持三种主要查询方式:Lambda、ExprExprString
其中 Lambda 最终也会先转换成 Expr,再统一生成 SQL。
本文档聚焦“如何选型”和“常见查询入口”;如果你要系统学习 Expr 的构造方式、静态方法、扩展方法和组合语义,请优先阅读Expr 使用指南

1. 三种查询方式对比

方式 语法 更适合 类型安全
Lambda u => u.Age > 18 固定条件、业务语义清晰 ✅ 强
Expr Expr.Prop("Age") > 18 动态拼装、查询构造器、多条件后台筛选 ✅ 编译期
ExprString $"WHERE {expr}" DAO 中的条件片段或完整 SQL ❌ 运行时

1.1 经验性选择

2. Lambda 查询入口

2.1 基础过滤

var users = await userService.SearchAsync(u => u.Age >= 18);
var users = await userService.SearchAsync(u => u.UserName.Contains("admin"));
var users = await userService.SearchAsync(u => new[] { 1, 2, 3 }.Contains(u.Id));

2.2 排序与分页

var page = await userService.SearchAsync(
    q => q.Where(u => u.Age >= 18)
          .OrderByDescending(u => u.CreateTime)
          .Skip(0)
          .Take(20)
);

2.3 变量捕获与参数化

var keyword = "admin";
var users = await userService.SearchAsync(u => u.UserName.Contains(keyword));

Lambda 外定义的变量会被参数化。
如果是 DateTime.Now 这类值,希望参数化时应先赋给变量。

3. ExistsExistsRelated

3.1 显式 Exists

Lambda 写法:

using static LiteOrm.Common.Expr;

var users = await userService.SearchAsync(
    u => Exists<Department>(d => d.Id == u.DeptId && d.Name == "研发中心")
);

Expr 写法:

using static LiteOrm.Common.Expr;

var expr = Exists<Department>(
    Prop("Id") == Prop("T0", "DeptId") & Prop("Name") == "研发中心"
);
var users = await userService.SearchAsync(expr);

适合你想自己控制关联条件的场景。

3.2 自动关联 ExistsRelated

Lambda 写法:

using static LiteOrm.Common.Expr;

var users = await userService.SearchAsync(
    u => ExistsRelated<DepartmentView>(d => d.Name == "研发中心")
);

Expr 写法:

using static LiteOrm.Common.Expr;

var expr = ExistsRelated<DepartmentView>(Prop("Name") == "研发中心");
var users = await userService.SearchAsync(expr);

适合模型里已经声明好关联路径,只想“按关联表条件过滤主表”的场景。
匹配逻辑、继承链规则和 ConstFilter 行为请看关联查询

4. Expr 查询入口

using static LiteOrm.Common.Expr;

LogicExpr condition = null;

if (minAge.HasValue)
    condition &= Prop("Age") >= minAge.Value;

if (!string.IsNullOrWhiteSpace(keyword))
    condition &= Prop("UserName").Contains(keyword);

var users = await userService.SearchAsync(condition);

Expr 最大的价值在于“先构造,再组合,再复用”。
而 Lambda 查询也会先转成 Expr 再继续生成 SQL,所以两者并不是两套互相隔离的能力体系。
有关 Expr 的详细说明,请转到:Expr 使用指南

5. ExprString 插值字符串

ExprString 允许你在插值字符串中直接嵌入 Expr 对象和参数,适合 DAO 层里需要手动构造 Search 条件片段或完整 SQL 的场景。Service 层没有对应的公开查询重载。

5.1 基本用法

using static LiteOrm.Common.Expr;

var condition = Prop("Age") >= 18;
var users = await userViewDAO.Search(
    $"WHERE {condition} ORDER BY CreateTime DESC"
).ToListAsync();

5.2 参数化与安全性

using static LiteOrm.Common.Expr;

int minAge = 18;
var result = await userViewDAO.Search(
    $"WHERE {Prop("Age")} >= {minAge}"
).ToListAsync();

插值里的普通值仍会按参数处理;插值里的 Expr 对象会先转成对应 SQL 片段再拼进去。
所以推荐优先插入 Expr.Prop(...)Expr.Value(...)LogicExpr 这类结构化对象,而不是在字符串里手写大量列名和值。

5.3 使用边界与推荐写法

建议:

var result = await dataViewDAO.Search(
    $"SELECT [Id], [UserName] FROM [Users] WHERE [Age] >= {minAge}",
    isFull: true
).GetResultAsync();
var result = await dataViewDAO.Search(
    $"""
    WITH ActiveUsers AS (
        SELECT Id, UserName, Age
        FROM Users
        WHERE Age >= {minAge}
    )
    SELECT Id, UserName, Age
    FROM ActiveUsers
    """,
    isFull: true
).GetResultAsync();

6. Service 与 DAO 查询

6.1 Service

using static LiteOrm.Common.Expr;

var users1 = await userService.SearchAsync(u => u.Age >= 18);
var users2 = await userService.SearchAsync(Prop("Age") >= 18);

6.2 DAO

using static LiteOrm.Common.Expr;

var users1 = await userViewDAO.Search(u => u.Age >= 18).ToListAsync();
var users2 = await userViewDAO.Search(Prop("Age") >= 18).ToListAsync();
var users3 = await userViewDAO.Search($"WHERE {Prop("Age")} > {minAge}").ToListAsync();

7. 相关链接