ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

告别硬编码!用SqlSugar的IConditionalModel和WhereIF实现C#动态查询(附完整代码示例)

2026/8/19 2:24:25 拓冰建站 浏览量
告别硬编码!用SqlSugar的IConditionalModel和WhereIF实现C#动态查询(附完整代码示例)

告别硬编码!用SqlSugar的IConditionalModel和WhereIF实现C#动态查询(附完整代码示例)

在后台管理系统、报表工具或搜索功能的开发中,动态查询是最常见的需求之一。用户可能根据不同的筛选条件组合查询数据,而开发者需要灵活应对这些变化。传统的字符串拼接SQL或复杂的Expression动态构建不仅难以维护,还存在SQL注入风险。本文将深入探讨如何利用SqlSugar的IConditionalModel和WhereIF,提供一套安全、可维护的动态查询方案。

1. 动态查询的常见痛点与解决方案

开发中我们常遇到这样的场景:用户在前端选择不同的筛选条件,后端需要根据这些条件动态构建查询。比如一个电商后台,管理员可能根据商品名称、价格范围、库存状态等任意组合查询商品。

传统解决方案主要有三种:

  1. 字符串拼接SQL:直接拼接SQL字符串,简单但存在SQL注入风险,且难以维护。
  2. 动态构建Expression:使用Expression树动态构建查询条件,类型安全但代码复杂。
  3. 链式调用Where:根据条件逐个调用Where方法,代码清晰但条件组合复杂时难以处理。

SqlSugar提供了两种更优雅的方案:IConditionalModelWhereIF。下面我们通过实际案例对比这几种方式的优劣。

// 字符串拼接SQL(不推荐) string sql = "SELECT * FROM Products WHERE 1=1"; if (!string.IsNullOrEmpty(name)) sql += $" AND Name LIKE '%{name}%'"; // SQL注入风险! // 动态Expression(复杂) Expression<Func<Product, bool>> expr = p => true; if (!string.IsNullOrEmpty(name)) expr = expr.And(p => p.Name.Contains(name)); // 链式Where(条件多时冗长) var query = db.Queryable<Product>(); if (!string.IsNullOrEmpty(name)) query = query.Where(p => p.Name.Contains(name));

2. 使用WhereIF简化条件查询

WhereIF是SqlSugar提供的一个非常实用的方法,它只在第一个参数为true时应用后面的查询条件。这种方式比传统的if判断更加简洁。

public ISugarQueryable<T> WhereIF(bool isWhere, Expression<Func<T, bool>> expression)

2.1 基础用法

假设我们有一个产品查询接口,支持按名称、价格范围和库存状态筛选:

public List<Product> SearchProducts(string name, decimal? minPrice, decimal? maxPrice, bool? inStock) { return db.Queryable<Product>() .WhereIF(!string.IsNullOrEmpty(name), p => p.Name.Contains(name)) .WhereIF(minPrice.HasValue, p => p.Price >= minPrice.Value) .WhereIF(maxPrice.HasValue, p => p.Price <= maxPrice.Value) .WhereIF(inStock.HasValue, p => p.Stock > 0 == inStock.Value) .ToList(); }

提示:WhereIF的条件判断应该尽可能简单,复杂逻辑建议提前计算好bool值再传入。

2.2 多条件组合

WhereIF也支持更复杂的条件组合,比如同时满足多个条件才应用查询:

bool shouldFilterPrice = minPrice.HasValue || maxPrice.HasValue; return db.Queryable<Product>() .WhereIF(!string.IsNullOrEmpty(name), p => p.Name.Contains(name)) .WhereIF(shouldFilterPrice, p => (!minPrice.HasValue || p.Price >= minPrice.Value) && (!maxPrice.HasValue || p.Price <= maxPrice.Value)) .ToList();

3. 使用IConditionalModel实现动态查询

对于更复杂的动态查询场景,特别是条件需要动态生成时,IConditionalModel提供了更大的灵活性。SqlSugar内置了两种实现:ConditionalModelConditionalCollections

3.1 ConditionalModel基础用法

ConditionalModel表示一个简单的查询条件,包含字段名、值和比较类型:

public class ConditionalModel : IConditionalModel { public string FieldName { get; set; } // 字段名 public string FieldValue { get; set; } // 值 public ConditionalType ConditionalType { get; set; } // 比较类型 }

常见比较类型包括:

  • Equal:等于
  • Like:模糊匹配
  • GreaterThan:大于
  • LessThan:小于
  • In:在集合中

示例代码:

var conditions = new List<IConditionalModel> { new ConditionalModel { FieldName = "Name", FieldValue = "手机", ConditionalType = ConditionalType.Like }, new ConditionalModel { FieldName = "Price", FieldValue = "1000", ConditionalType = ConditionalType.GreaterThan } }; var products = db.Queryable<Product>().Where(conditions).ToList();

3.2 处理复杂条件组合

ConditionalCollections允许我们构建更复杂的条件逻辑(AND/OR组合):

var complexCondition = new ConditionalCollections { ConditionalList = new List<KeyValuePair<WhereType, ConditionalModel>> { new KeyValuePair<WhereType, ConditionalModel>( WhereType.And, new ConditionalModel { FieldName = "Category", FieldValue = "1", ConditionalType = ConditionalType.Equal }), new KeyValuePair<WhereType, ConditionalModel>( WhereType.Or, new ConditionalModel { FieldName = "Price", FieldValue = "500", ConditionalType = ConditionalType.LessThan }), new KeyValuePair<WhereType, ConditionalModel>( WhereType.Or, new ConditionalModel { FieldName = "Stock", FieldValue = "0", ConditionalType = ConditionalType.GreaterThan }) } }; // 生成的SQL类似:WHERE (Category = 1) OR (Price < 500) OR (Stock > 0) var results = db.Queryable<Product>().Where(complexCondition).ToList();

3.3 动态构建查询条件

在实际应用中,我们通常需要根据用户输入动态构建条件。下面是一个完整的动态查询示例:

public List<Product> DynamicQuery(Dictionary<string, string> filters) { var conditions = new List<IConditionalModel>(); foreach (var filter in filters) { if (string.IsNullOrEmpty(filter.Value)) continue; var condition = new ConditionalModel { FieldName = filter.Key, FieldValue = filter.Value }; // 根据字段类型设置不同的比较方式 switch (filter.Key) { case "Name": condition.ConditionalType = ConditionalType.Like; break; case "Price": condition.ConditionalType = decimal.TryParse(filter.Value, out _) ? ConditionalType.Equal : ConditionalType.NoEqual; break; case "Stock": condition.ConditionalType = ConditionalType.GreaterThan; break; default: condition.ConditionalType = ConditionalType.Equal; break; } conditions.Add(condition); } return conditions.Count > 0 ? db.Queryable<Product>().Where(conditions).ToList() : db.Queryable<Product>().ToList(); }

4. 高级技巧与最佳实践

4.1 性能优化建议

动态查询虽然灵活,但也需要注意性能问题:

  1. 避免过度使用OR条件:大量OR条件可能导致索引失效
  2. 合理使用参数化查询:IConditionalModel会自动参数化,但直接拼接SQL不会
  3. 考虑分页:大数据量查询务必配合分页使用
// 好的实践:分页+条件 var pagedResult = db.Queryable<Product>() .Where(conditions) .ToPageList(pageNumber, pageSize);

4.2 与Entity Framework对比

相比于EF Core的动态查询方案,SqlSugar的IConditionalModel有几个优势:

特性SqlSugar IConditionalModelEF Core 动态LINQ
学习曲线
条件组合灵活性
性能
可维护性
原生SQL支持有限

4.3 实际项目中的应用模式

在实际项目中,我通常会采用以下模式组织动态查询代码:

public class ProductQueryBuilder { private readonly List<IConditionalModel> _conditions = new(); public ProductQueryBuilder WithName(string name) { if (!string.IsNullOrEmpty(name)) _conditions.Add(new ConditionalModel { FieldName = nameof(Product.Name), FieldValue = name, ConditionalType = ConditionalType.Like }); return this; } public ProductQueryBuilder WithPriceRange(decimal? min, decimal? max) { if (min.HasValue) _conditions.Add(new ConditionalModel { FieldName = nameof(Product.Price), FieldValue = min.Value.ToString(), ConditionalType = ConditionalType.GreaterThan }); if (max.HasValue) _conditions.Add(new ConditionalModel { FieldName = nameof(Product.Price), FieldValue = max.Value.ToString(), ConditionalType = ConditionalType.LessThan }); return this; } public ISugarQueryable<Product> Build(ISqlSugarClient db) { return _conditions.Count > 0 ? db.Queryable<Product>().Where(_conditions) : db.Queryable<Product>(); } } // 使用示例 var query = new ProductQueryBuilder() .WithName("手机") .WithPriceRange(1000, 5000) .Build(db); var results = query.ToList();

这种建造者模式让代码更加清晰,也便于单元测试。