我有一个场景,我必须从数据库中获取 18000 条记录,并将其转换为 DTO。 refId 总数 = 数据库中引用表的 18000 个唯一 id。
int batchSize = 1000;
var refBatchList = new List<List<int>>();
for (var i = 0; i < refIds.Count; i += batchSize)
{
refBatchList.Add(refIds.Skip(i).Take(batchSize).ToList());
}
var dbDataRetrievalTasks = refBatchList.Select(async refIdsBatch => await GetReferencesAsync(refIdsBatch, new data.Entities()));
var results = await Task.WhenAll(dbDataRetrievalTasks);
上面的代码部分创建了多个并行执行的任务,并调用下面的方法从数据库异步检索数据。
private async Task<List<reference>> GetReferencesAsync(List<int> ids, JIVE.data.Entities db)
{
var result = await db.Set<reference>()
.Where(x => ids.Contains(x.reference_id))
.AsNoTracking()
.ToListAsync();
return result;
}
我的问题是,由于我计划并行进行数据库调用,因此我使用多个数据库连接。在这些场景中,由于有 18 个批次,因此将有 18 个不同的数据库连接。
所以我想知道是否可以从数据库中检索这样的数据。该方法有哪些缺点?有没有更好的方法来实现这一目标。
我知道如果有更多批次,tasks.whenAll() 会创建多个任务,这可能会限制线程池。但在我的场景中,我可以获得的最大批次是 20。
对于较大的 ID 集,请查看 AsQueryableValues(set) (https://github.com/yv989c/BlazarTech.QueryableValues),它在幕后利用 OPENJSON。这将允许您在一次调用中合理地检索所需的 18k 行。
var references = db.Set<reference>()
.Where(x => db.AsQueryableValues(refIds).Contains(x.reference_id))
.AsNoTracking()
.ToListAsync();
在读取场景中,可以通过仅使用参考中所需的列投影到视图模型/DTO 来进一步改进这一点。 (例如,如果参考文献是大量不同大小的列,但您只需要少数列)