SqlSugar 动态表达式查询功能解析与实战应用
引言:告别硬编码查询的束缚
在日常开发中,你是否经常遇到这样的场景:需要根据用户输入动态构建查询条件,但传统的LINQ表达式无法满足灵活多变的业务需求?或者面对复杂的多条件组合查询时,代码变得冗长且难以维护?
SqlSugar的**动态表达式查询(Dynamic Expression Query)**功能正是为解决这些痛点而生。它提供了强大的表达式构建能力,让你能够以编程方式动态生成查询条件,彻底告别硬编码的束缚。
动态表达式核心组件解析
Expressionable :表达式构建利器
SqlSugar通过Expressionable<T>类提供动态表达式构建能力,支持1-12个泛型参数的表达式组合:
public class Expressionable<T> where T : class, new()
{
Expression<Func<T, bool>> _exp = null;
// 添加AND条件
public Expressionable<T> And(Expression<Func<T, bool>> exp)
{
if (_exp == null)
_exp = exp;
else
_exp = Expression.Lambda<Func<T, bool>>(
Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters);
return this;
}
// 条件性添加AND
public Expressionable<T> AndIF(bool isAnd, Expression<Func<T, bool>> exp)
{
if (isAnd) And(exp);
return this;
}
// 添加OR条件
public Expressionable<T> Or(Expression<Func<T, bool>> exp)
{
if (_exp == null)
_exp = exp;
else
_exp = Expression.Lambda<Func<T, bool>>(
Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters);
return this;
}
// 条件性添加OR
public Expressionable<T> OrIF(bool isOr, Expression<Func<T, bool>> exp)
{
if (isOr) Or(exp);
return this;
}
// 转换为表达式
public Expression<Func<T, bool>> ToExpression()
{
return _exp ?? (it => true);
}
}
多表关联表达式支持
SqlSugar还提供了多表关联的表达式构建器:
// 双表表达式构建器
public class Expressionable<T, T2> where T : class, new() where T2 : class, new()
{
// 支持AND/OR操作,与单表类似
}
// 三表表达式构建器
public class Expressionable<T, T2, T3> where T : class, new() where T2 : class, new() where T3 : class, new()
{
// 支持AND/OR操作
}
实战应用场景
场景1:动态多条件搜索
// 用户搜索条件
var searchModel = new UserSearchModel
{
Name = "张三",
Age = 25,
Department = "技术部"
};
// 动态构建查询表达式
var exp = Expressionable.Create<User>()
.AndIF(!string.IsNullOrEmpty(searchModel.Name), u => u.Name.Contains(searchModel.Name))
.AndIF(searchModel.Age > 0, u => u.Age == searchModel.Age)
.AndIF(!string.IsNullOrEmpty(searchModel.Department), u => u.Department == searchModel.Department);
var users = db.Queryable<User>().Where(exp.ToExpression()).ToList();
场景2:复杂条件组合查询
// 构建复杂的OR条件组合
var keywords = new string[] { "紧急", "重要", "高优先级" };
var exp = Expressionable.Create<Task>();
foreach (var keyword in keywords)
{
exp.Or(t => t.Title.Contains(keyword) || t.Description.Contains(keyword));
}
// 添加额外的AND条件
exp.And(t => t.Status == TaskStatus.Active)
.And(t => t.DueDate >= DateTime.Today);
var tasks = db.Queryable<Task>().Where(exp.ToExpression()).ToList();
场景3:多表关联动态查询
// 用户和部门的关联查询
var exp = Expressionable.Create<User, Department>()
.AndIF(!string.IsNullOrEmpty(userName), (u, d) => u.Name.Contains(userName))
.AndIF(departmentId > 0, (u, d) => u.DepartmentId == departmentId)
.AndIF(!string.IsNullOrEmpty(departmentName), (u, d) => d.Name.Contains(departmentName));
var result = db.Queryable<User, Department>((u, d) => u.DepartmentId == d.Id)
.Where(exp.ToExpression())
.Select((u, d) => new UserDto
{
UserName = u.Name,
DepartmentName = d.Name
})
.ToList();
高级特性深度解析
WhereIF条件方法
SqlSugar提供了内置的WhereIF方法,简化条件查询:
var query = db.Queryable<User>()
.WhereIF(!string.IsNullOrEmpty(name), u => u.Name.Contains(name))
.WhereIF(age > 0, u => u.Age == age)
.WhereIF(departmentId > 0, u => u.DepartmentId == departmentId)
.ToList();
表达式性能优化
表达式组合模式
// 模块化表达式构建
public Expression<Func<User, bool>> BuildNameFilter(string name)
{
return u => u.Name.Contains(name);
}
public Expression<Func<User, bool>> BuildAgeFilter(int? minAge, int? maxAge)
{
var exp = Expressionable.Create<User>();
if (minAge.HasValue) exp.And(u => u.Age >= minAge.Value);
if (maxAge.HasValue) exp.And(u => u.Age <= maxAge.Value);
return exp.ToExpression();
}
// 组合使用
var finalExp = Expressionable.Create<User>()
.And(BuildNameFilter("张"))
.And(BuildAgeFilter(20, 30))
.ToExpression();
最佳实践与性能考量
实践1:表达式缓存策略
// 使用静态字段缓存常用表达式
private static readonly Expression<Func<User, bool>> ActiveUsersExpression =
u => u.IsActive && u.Status == UserStatus.Normal;
// 使用时组合
var exp = Expressionable.Create<User>()
.And(ActiveUsersExpression)
.AndIF(condition, u => u.Age > 18)
.ToExpression();
实践2:避免表达式过度复杂化
// 不推荐:过于复杂的单表达式
var badExp = u => (u.Name.Contains("A") || u.Name.Contains("B")) &&
(u.Age > 20 || u.Age < 30) &&
(u.Department == "IT" || u.Department == "HR");
// 推荐:分步构建,清晰易维护
var goodExp = Expressionable.Create<User>()
.And(u => u.Name.Contains("A") || u.Name.Contains("B"))
.And(u => u.Age > 20 || u.Age < 30)
.And(u => u.Department == "IT" || u.Department == "HR")
.ToExpression();
性能对比表格
| 查询方式 | 执行时间 | 内存占用 | 可维护性 | 适用场景 |
|---|---|---|---|---|
| 硬编码LINQ | ⚡️ 最快 | 🟢 最低 | 🔴 差 | 固定条件查询 |
| Expressionable | 🟡 中等 | 🟡 中等 | 🟢 优秀 | 动态条件查询 |
| 字符串SQL | 🔴 最慢 | 🔴 最高 | 🟡 一般 | 极端复杂查询 |
常见问题与解决方案
问题1:表达式构建错误
// 错误:直接拼接表达式
Expression<Func<User, bool>> exp1 = u => u.Age > 18;
Expression<Func<User, bool>> exp2 = u => u.Name.Contains("张");
// var wrong = exp1 || exp2; // 编译错误
// 正确:使用Expressionable组合
var correct = Expressionable.Create<User>()
.And(exp1)
.Or(exp2)
.ToExpression();
问题2:空值处理
// 安全的空值处理
var exp = Expressionable.Create<User>();
if (!string.IsNullOrEmpty(searchKey))
{
exp.And(u => u.Name.Contains(searchKey) || u.Email.Contains(searchKey));
}
// 如果没有条件,返回所有数据
问题3:性能优化
// 使用AsEnumerable()延迟执行复杂表达式
var complexQuery = db.Queryable<User>()
.Where(u => u.IsActive)
.AsEnumerable() // 切换到内存中处理
.Where(u => ComplexBusinessLogic(u))
.ToList();
总结与展望
SqlSugar的动态表达式查询功能为.NET开发者提供了强大的灵活性和表达能力。通过Expressionable<T>系列类,我们可以:
- 动态构建复杂查询条件,适应多变的业务需求
- 实现条件组合的模块化,提高代码可维护性
- 支持多表关联查询,满足复杂业务场景
- 提供性能优化机制,平衡灵活性与执行效率
在实际项目中,建议:
- 对于简单固定条件,使用原生LINQ
- 对于中等复杂度的动态条件,使用Expressionable
- 对于极端复杂的查询,考虑分步处理或存储过程
随着.NET生态的不断发展,SqlSugar的动态表达式功能将继续演进,为开发者提供更强大、更高效的查询解决方案。掌握这一技能,将让你在数据处理领域游刃有余,轻松应对各种复杂的业务查询需求。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



