在实际业务系统中,批量查询是最高频的数据库操作。SqlSugar提供了丰富而强大的批量查询功能,能够显著提升数据检索效率。本文将全面解析SqlSugar的批量查询技术。
1. 基础批量查询方法
1.1 主键列表批量查询
// 根据主键列表批量查询
var ids = new List<long> { 1, 2, 3, 4, 5 };
var list = db.Queryable<Order>().In(ids).ToList();
// 异步版本
var list = await db.Queryable<Order>().In(ids).ToListAsync();
// 只查询特定字段
var result = await db.Queryable<Order>()
.Where(o => ids.Contains(o.Id))
.Select(o => new { o.Id, o.OrderNo, o.Amount })
.ToListAsync();
1.2 条件批量查询
// 多条件批量查询
var result = db.Queryable<Order>()
.Where(o => o.Status == OrderStatus.Completed)
.Where(o => o.CreateTime >= DateTime.Now.AddDays(-7))
.WhereIF(!string.IsNullOrEmpty(keyword), o => o.OrderNo.Contains(keyword))
.ToList();
// 复杂条件组合
var query = db.Queryable<Order>();
if (statusList != null && statusList.Any())
query = query.Where(o => statusList.Contains(o.Status));
if (minAmount.HasValue)
query = query.Where(o => o.Amount >= minAmount.Value);
var result = query.ToList();
2. 高性能批量查询方案
2.1 分页批量查询(大数据量推荐)
public async Task<PageResult<T>> BatchQueryInPages<T>(
Expression<Func<T, bool>> whereExpression,
int pageSize = 1000,
string orderBy = "Id") where T : class, new()
{
var result = new PageResult<T> { Data = new List<T>() };
var hasMoreData = true;
var pageIndex = 1;
while (hasMoreData)
{
try
{
var pageData = await db.Queryable<T>()
.Where(whereExpression)
.OrderBy(orderBy)
.ToPageListAsync(pageIndex, pageSize);
if (pageData == null || !pageData.Any())
{
hasMoreData = false;
break;
}
result.Data.AddRange(pageData);
result.TotalCount += pageData.Count;
// 如果返回数据少于页大小,说明没有更多数据
if (pageData.Count < pageSize)
{
hasMoreData = false;
}
pageIndex++;
Console.WriteLine($"已加载 {result.TotalCount} 条记录...");
}
catch (Exception ex)
{
Console.WriteLine($"第{pageIndex}页查询失败: {ex.Message}");
break;
}
}
return result;
}
// 使用示例
var result = await BatchQueryInPages<Order>(
o => o.CreateTime >= DateTime.Now.AddMonths(-1),
2000, "CreateTime DESC");
2.2 并行批量查询
public async Task<List<T>> ParallelBatchQuery<T>(
List<Expression<Func<T, bool>>> conditions) where T : class, new()
{
var tasks = conditions.Select(condition =>
db.Queryable<T>().Where(condition).ToListAsync()
).ToArray();
var results = await Task.WhenAll(tasks);
return results.SelectMany(x => x).ToList();
}
// 分片并行查询
public async Task<List<T>> ShardedParallelQuery<T>(
Expression<Func<T, bool>> baseCondition,
string shardColumn,
int shardCount) where T : class, new()
{
var tasks = new List<Task<List<T>>>();
for (int i = 0; i < shardCount; i++)
{
int currentShard = i;
var task = Task.Run(async () =>
{
return await db.Queryable<T>()
.Where(baseCondition)
.Where($"{shardColumn} % {shardCount} = {currentShard}")
.ToListAsync();
});
tasks.Add(task);
}
var results = await Task.WhenAll(tasks);
return results.SelectMany(x => x).ToList();
}
3. 高级批量查询技巧
3.1 多表关联批量查询
// 链式多表查询
var result = await db.Queryable<Order>()
.LeftJoin<User>((o, u) => o.UserId == u.Id)
.LeftJoin<OrderDetail>((o, u, od) => o.Id == od.OrderId)
.Where((o, u, od) => o.Status == OrderStatus.Completed && u.VipLevel > 1)
.Select((o, u, od) => new OrderDto
{
OrderId = o.Id,
OrderNo = o.OrderNo,
UserName = u.Name,
TotalAmount = o.Amount,
ItemCount = SqlFunc.AggregateSum(od.Quantity)
})
.GroupBy((o, u, od) => new { o.Id, o.OrderNo, u.Name })
.ToListAsync();
// 使用Includes进行关联加载
var orders = await db.Queryable<Order>()
.Includes(o => o.User) // 加载用户信息
.Includes(o => o.OrderDetails) // 加载订单详情
.Includes(o => o.OrderDetails.First().Product) // 加载商品信息
.Where(o => o.CreateTime >= DateTime.Now.AddDays(-7))
.ToListAsync();
3.2 动态条件批量查询
public async Task<List<Order>> DynamicBatchQuery(OrderQueryDto query)
{
var exp = Expressionable.Create<Order>();
// 动态构建条件
if (!string.IsNullOrEmpty(query.OrderNo))
exp.And(o => o.OrderNo.Contains(query.OrderNo));
if (query.Status.HasValue)
exp.And(o => o.Status == query.Status.Value);
if (query.StartTime.HasValue)
exp.And(o => o.CreateTime >= query.StartTime.Value);
if (query.EndTime.HasValue)
exp.And(o => o.CreateTime <= query.EndTime.Value);
if (query.MinAmount.HasValue)
exp.And(o => o.Amount >= query.MinAmount.Value);
if (query.MaxAmount.HasValue)
exp.And(o => o.Amount <= query.MaxAmount.Value);
var sqlQuery = db.Queryable<Order>().Where(exp.ToExpression());
// 动态排序
if (!string.IsNullOrEmpty(query.SortField))
{
var sortOrder = query.SortOrder?.ToLower() == "desc" ? " DESC" : " ASC";
sqlQuery = sqlQuery.OrderBy($"{query.SortField}{sortOrder}");
}
else
{
sqlQuery = sqlQuery.OrderBy("Id DESC");
}
// 分页
if (query.PageSize > 0)
{
sqlQuery = sqlQuery.ToPageList(query.PageIndex, query.PageSize);
}
return await sqlQuery.ToListAsync();
}
4. 性能优化策略
4.1 查询字段优化
public class QueryOptimizationHelper
{
// 只查询需要的字段
public async Task<List<OrderSimpleDto>> OptimizedQuery()
{
return await db.Queryable<Order>()
.Where(o => o.CreateTime >= DateTime.Now.AddMonths(-1))
.Select(o => new OrderSimpleDto
{
Id = o.Id,
OrderNo = o.OrderNo,
Amount = o.Amount,
Status = o.Status
})
.ToListAsync();
}
// 使用NoTracking提高查询性能
public async Task<List<Order>> NoTrackingQuery()
{
return await db.Queryable<Order>()
.With(SqlWith.NoLock) // SQL Server的NOLOCK
.ASNoTracking() // 不跟踪实体状态
.Where(o => o.Status == OrderStatus.Completed)
.ToListAsync();
}
// 批量查询使用索引优化
public async Task<List<Order>> IndexOptimizedQuery(List<long> ids)
{
// 分批查询避免IN条件过长
var batchSize = 1000;
var result = new List<Order>();
for (int i = 0; i < ids.Count; i += batchSize)
{
var batchIds = ids.Skip(i).Take(batchSize).ToList();
var batchResult = await db.Queryable<Order>()
.Where(o => batchIds.Contains(o.Id))
.ToListAsync();
result.AddRange(batchResult);
}
return result;
}
}
SqlSugar批量查询的最佳实践建议:
-
小数据量(万条以内):使用直接IN查询或条件查询
-
中等数据量(万条到十万条):使用分页查询
-
大数据量(十万条以上):必须使用分页查询,考虑并行处理
-
复杂关联查询:使用Includes或Join进行关联加载
-
高频查询:结合缓存策略提升性能
关键优化技巧:
-
字段优化:只查询需要的字段,避免SELECT *
-
索引利用:确保查询条件使用合适的索引
-
分页策略:大数据量使用Keyset分页替代OFFSET分页
-
缓存应用:合理使用查询缓存减少数据库压力
-
监控告警:添加查询性能监控和慢查询告警
1009

被折叠的 条评论
为什么被折叠?



