我需要用 C# .net core 编写一个控制台应用程序。此控制台应用程序应订阅事件中心。它侦听事件中心,当它通过事件中心接收到消息时,它会读取消息并进行处理。该消息包含客户 ID 和处理数据所需的一些其他信息。
在数据库中,我们为每个客户创建了数据库。数据库名称等于客户 ID。现在 C# 服务需要根据消息中收到的客户 ID 动态连接到数据库。
我正在使用实体框架来编写代码。
我在 startup.cs 中使用 DBConext 在 Web API 中做了类似的工作,如下所示:
services.AddDbContext<CustomerContext>(options =>
{
var serviceProvider = services.BuildServiceProvider();
var httpRouteData = serviceProvider.GetService<IHttpContextAccessor>()?.HttpContext?.GetRouteData();
var db = httpRouteData?.Values["customerId"]?.ToString();
db = db?.Replace('-', '_');
options.UseNpgsql(
new NpgsqlConnectionStringBuilder
{
Host = "Hostname",
Port = "port",
SslMode = SslMode.Require,
Username = "username",
Database = db,
Password = "password",
Timeout = 1024,
CommandTimeout = 60000
}.ConnectionString
);
});
所以每个请求,基于 httpcontext 路由数据中的 customerId,我们能够动态地形成连接字符串。并通过依赖注入使用这个 DBContext。如何在控制台应用程序中实现此功能?
您可以创建一个方法来为客户每次获取 dbcontext connectionstring。
public class CustomerContextFactory : IDisposable
{
private readonly Dictionary<string, CustomerContext> _dbContexts = new Dictionary<string, CustomerContext>();
public CustomerContext GetContext(string customerId)
{
if (!_dbContexts.TryGetValue(customerId, out var context))
{
var connectionString = new NpgsqlConnectionStringBuilder
{
Host = "Hostname",
Port = "port",
SslMode = SslMode.Require,
Username = "username",
Database = customerId.Replace('-', '_'),
Password = "password",
Timeout = 1024,
CommandTimeout = 60000
}.ConnectionString;
var optionsBuilder = new DbContextOptionsBuilder<CustomerContext>()
.UseNpgsql(connectionString);
context = new CustomerContext(optionsBuilder.Options);
_dbContexts.Add(customerId, context);
}
return context;
}
public void Dispose()
{
foreach (var context in _dbContexts.Values)
{
context.Dispose();
}
}
}
使用它获取消息中客户 ID 的 DbContext 实例:
void HandleEvent(EventData eventData)
{
var customerId = eventData.Properties["CustomerId"].ToString();
using (var contextFactory = new CustomerContextFactory())
using (var context = contextFactory.GetContext(customerId))
{
// Use the context to process the message
// ...
}
}