c# - 当动态数据确定连接字符串时,创建 DbContext 的好模式是什么
问题描述
我从另一个 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。
解决方案
您可以将用于创建的逻辑移动ClientContext
到另一个负责的类中(根据 SOLID 原则),例如并为每个客户DbContextFactory
存储 created 。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();
推荐阅读
- r - 在 R 中,它以数字形式出现,尝试使用 ifelse 语法提取与条件匹配的字符
- python - 如何在 python 中将 dir 结果转换为 csv 或 json?
- javascript - 在 jQuery 中使用一个具有 4 个单独 ID 的变量时遇到问题
- java - 尝试从 JSONObject 中获取 JSONArray 失败
- objective-c - 为什么我的故事板没有加载?
- java - okhttp缓存:如何在网络连接中先获取缓存数据然后获取网络数据?
- sql-server - 无法使用 odbc 驱动程序 17 将数据插入加密列
- python - 按索引列表为每一行选择熊猫列
- java - 构造函数 csvreader(reader char) 已弃用错误
- android - 更改语言后不显示 Admob 广告