我从另一个Web API获取数据集。它可能包含来自不同客户端的多个记录。我必须转换这些数据并将它们写入客户端的数据库。每个客户端都有自己的数据库。客户端数据库的架构完全相同。
我创建了一个DbContext工厂,该工厂根据应用当前正在使用的客户端来创建DbContext的新实例。
public ClientDbContext CreateClientDbContext(string clientNumber)
{
var optionsBuilder = new DbContextOptionsBuilder<ClientDbContext>();
var clientConnection = string.Format(_configuration.GetConnectionString("clientConnection"), clientNumber);
optionsBuilder.UseSqlServer(clientConnection);
clientDbContext clientDbContext = new ClientDbContext(optionsBuilder.Options);
return clientDbContext;
}
我以这种方式使用工厂:
foreach (var case in caseList)
{
var clientDbContext = await _clientDbContextFactory.CreateClientDbContext(case.ClientNumber);
_clientRepository = new ClientRepository(clientDbContext);
var updatedCase = /// transform case here
await _clientRepository.CreateCases(updatedCase);
}
为什么有这样做的最佳选择? 几行数据可能具有相同的客户端,所以我想重用相同的ClientDbContext。
答案 0 :(得分:1)
您可以将创建ClientContext
的逻辑移到另一个负责任的类中(按照SOLID原则),类似于DbContextFactory
,并在其中存储为每个客户创建的DbContext
。像这样:
public class DbContextFactory
{
private readonly IConfiguration _configuration;
private readonly Dictionary<string, ClientDbContext> _clientContexts = new Dictionary<string, ClientDbContext>();
public DbContextFactory(IConfiguration configuration)
{
_configuration = configuration;
}
public ClientDbContext GetOrCreateClientContext(string clientNumber)
{
// if you have context already created - return it
if (_clientContexts.ContainsKey(clientNumber))
return _clientContexts[clientNumber];
var optionsBuilder = new DbContextOptionsBuilder<ClientDbContext>();
var clientConnection = string.Format(_configuration.GetConnectionString("clientConnection"), clientNumber);
optionsBuilder.UseSqlServer(clientConnection);
var clientDbContext = new ClientDbContext(optionsBuilder.Options);
_clientContexts[clientNumber] = clientDbContext;
return clientDbContext;
}
}
然后在您的工作程序类中,您可以按ClientNumber
对数据进行分组,为每个客户端创建(或已经创建)DbContext
和存储库,然后进行数据更新。
public class Worker
{
private readonly DbContextFactory _factory;
public Worker(DbContextFactory factory)
{
_factory = factory;
}
public async Task DoWorkAsync()
{
// group by ClientNumber
var groupedCases = caseList.GroupBy(x => x.ClientNumber);
foreach (var groupedCase in groupedCases)
{
// For each client create context and repository
var clientContext = _factory.GetOrCreateClientContext(groupedCase.Key);
var clientRepository = new ClientRepository(clientContext);
foreach (var @case in groupedCases)
{
var updatedCase = // transform case here
await clientRepository.CreateCases(updatedCase);
}
}
}
}
您可以使用依赖注入或仅创建以下类:
var factory = new DbContextFactory(yourConfiguration);
var worker = new Worker(factory);
await worker.DoWorkAsync();
答案 1 :(得分:0)
分批处理案例,因为这使您可以在继续下一个客户端连接之前重用客户端连接。像这样:
var batches = caseList.GroupBy(x => x.ClientNumber);
foreach (var batch in batches)
{
var clientDbContext = await _clientDbContextFactory.CreateClientDbContext(batch.ClientNumber);
_clientRepository = new ClientRepository(clientDbContext);
foreach (var item in batch)
{
var updatedCase = /// transform case here
await _clientRepository.CreateCases(updatedCase);
}
}
您也可以从一批任务中受益,但是您应该对此进行概要分析,看看是否可以从中获得任何收益。看起来可能像这样:
var tasksInBatch = new List<Task>();
foreach (var item in batch)
{
var updatedCase = /// transform case here
tasksInBatch.Add(_clientRepository.CreateCases(updatedCase));
}
await Task.WhenAll(tasksInBatch);