在C# asp.net实体框架中创建多个数据库连接以并行方式获取数据

问题描述 投票:0回答:1

我有一个场景,我必须从数据库中获取 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。

c# entity-framework task-parallel-library
1个回答
0
投票

对于较大的 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 来进一步改进这一点。 (例如,如果参考文献是大量不同大小的列,但您只需要少数列)

© www.soinside.com 2019 - 2024. All rights reserved.