上一篇
如何在C中高效实现数据库动态多条件查询?
- 行业动态
- 2025-05-14
- 1
在C#中实现多条件数据库查询时,通常采用参数化SQL语句,通过动态拼接WHERE子句结合AND/OR逻辑,使用SqlCommand添加参数避免注入,或通过LINQ的链式条件组合构建灵活查询,确保数据安全性与代码可维护性。
在C#开发中,处理数据库的多条件查询是高频需求,如何编写高效、安全且灵活的查询语句?本文提供4种主流方法,涵盖基础到进阶场景,并附赠性能优化技巧和安全防护实践。
基础拼接方案(适合简单场景)
通过逻辑运算符组合条件,需注意空值处理:
string sql = "SELECT * FROM Products WHERE 1=1"; if (!string.IsNullOrEmpty(productName)) sql += " AND ProductName LIKE @ProductName"; if (priceMin > 0) sql += " AND Price >= @PriceMin"; if (priceMax > 0) sql += " AND Price <= @PriceMax"; using var cmd = new SqlCommand(sql, connection); cmd.Parameters.AddWithValue("@ProductName", $"%{productName}%"); cmd.Parameters.AddWithValue("@PriceMin", priceMin); cmd.Parameters.AddWithValue("@PriceMax", priceMax);
注意:
WHERE 1=1
用于简化条件拼接,避免处理首个AND的复杂性
动态SQL构建(推荐复杂条件)
使用StringBuilder提升性能,同时避免SQL注入风险:
var conditions = new List<string>(); var parameters = new SqlParameterCollection(); if (!string.IsNullOrEmpty(keyword)) { conditions.Add("(Title LIKE @Keyword OR Description LIKE @Keyword)"); parameters.Add(new SqlParameter("@Keyword", $"%{keyword}%")); } if (categoryId != 0) { conditions.Add("CategoryID = @CategoryID"); parameters.Add(new SqlParameter("@CategoryID", categoryId)); } string whereClause = conditions.Count > 0 ? "WHERE " + string.Join(" AND ", conditions) : string.Empty; var finalSql = new StringBuilder("SELECT * FROM Articles") .Append(whereClause) .ToString();
LINQ表达式树(Entity Framework Core)
通过表达式动态构建查询,实现强类型安全:
IQueryable<Product> query = context.Products; if (!string.IsNullOrWhiteSpace(searchTerm)) query = query.Where(p => p.Name.Contains(searchTerm)); if (minPrice.HasValue) query = query.Where(p => p.Price >= minPrice.Value); if (maxPrice.HasValue) query = query.Where(p => p.Price <= maxPrice.Value); var results = await query.ToListAsync();
Dapper高级用法(推荐高性能场景)
var dynamicParams = new DynamicParameters(); var sqlBuilder = new StringBuilder("SELECT * FROM Users WHERE 1=1"); if (!string.IsNullOrEmpty(email)) { sqlBuilder.Append(" AND Email = @Email"); dynamicParams.Add("Email", email); } if (registrationDate.HasValue) { sqlBuilder.Append(" AND RegistrationDate >= @RegDate"); dynamicParams.Add("RegDate", registrationDate.Value); } var results = connection.Query<User>( sqlBuilder.ToString(), dynamicParams );
️ 安全防护要点
- 参数化查询:100%避免SQL注入攻击
- 输入验证:对用户输入进行格式校验
- 权限控制:数据库账号使用最小权限原则
- 日志审计:记录异常查询行为
性能优化技巧
- 对常用查询字段建立索引
- 避免使用
SELECT *
,明确指定返回字段 - 复杂查询使用存储过程
- 分页查询使用
OFFSET FETCH
语法 - 定期执行查询计划分析
常见错误排查
现象 | 解决方案 |
---|---|
查询超时 | 检查索引,优化where条件 |
结果不符合预期 | 打印最终SQL语句验证 |
参数类型错误 | 使用强类型参数(如AddWithValue ) |
空值处理异常 | 使用DBNull.Value 代替null |
实际应用场景
电商商品筛选:
var filters = new ProductFilter { CategoryIds = new List<int> {1, 5, 7}, PriceRange = (100, 500), IsInStock = true }; var query = @"SELECT SKU,ProductName,Price FROM Products WHERE CategoryID IN @Categories AND Price BETWEEN @MinPrice AND @MaxPrice AND StockQuantity > 0";
引用说明
- Microsoft SQL文档:参数化查询最佳实践
- OWASP TOP 10:SQL注入防护指南
- Stack Overflow 2025开发者调查报告:数据库操作常见问题统计