将Db查询结果划分为任意多个任务



我想将Db查询结果划分为我想要的尽可能多的任务。我该怎么办?例如,我想在同一时间将每300行分配给同一个进程,但每300行必须是不同的300行。

我不知道你是什么意思

我想在同一时间给同一个进程每300行

然而,将查询结果划分为任务列表的一种可能的解决方案是:
  • 记录总数:

    var count = await context.Entities.CountAsync();
    
  • 计算您需要的总数据库调用:

    const int take = 300;
    var dbCallsCount = Math.Ceiling((double)count / take);
    
  • 创建一个获取数据的方法(注意不能通过同一个DbContext对象运行并行查询):

    public async Task<List<Entity>> FetchDataAsync(int page, int take)
    {
    using(var context = new DbContext("ConnectionString"))
    {
    var result = await context.Entities
    .AsNoTracking()
    .Skip((page - 1) * take) 
    .Take(take)
    .ToListAsync();
    return result;
    }
    }
    
  • 创建一个获取数据的任务列表:

    var taskList = new List<Task<List<Entity>>>();
    for(var i = 0; i < dbCallsCount; i++)
    taskList.Add(FetchDataAsync(i, take));
    var result = await Task.WhenAll(taskList);
    

它可以是一个通用的方法来获取数据的任务列表:

public async Task<List<Task<List<TEntity>>>> DivideDbQueryIntoTasks<TEntity>(int take) where TEntity : class 
{
int count;
using(var context = new DbContext("ConnectionString"))
{
count = await context.DbSet<TEntity>.CountAsync();
}
var dbCallsCount = Math.Ceiling((double)count / take);

// Local function
async Task<List<TEntity>> FetchDataAsync<TEntity>(int page, int take)
{
using(var context = new DbContext("ConnectionString"))
{
var result = await context.DbSet<TEntity>
.AsNoTracking()
.Skip((page - 1) * take) 
.Take(take)
.ToListAsync();

return result;
}
}
var taskList = new List<Task<List<TEntity>>>();
for(var i = 0; i < dbCallsCount; i++)
taskList.Add(FetchDataAsync<TEntity>(i, take));
return taskList;
}

然后这样调用:

var tasks = await DivideDbQueryIntoTasks<MyEntity>(300);
foreach (Task<List<IdentityUser>> task in tasks)
{
...
}

最新更新