Я разрабатываю WebAPI в .Net Core 2.2.Мне нужен пользовательский объект доступа к данным для запроса данных.Однако мне нужны разные соединения для разных задач.Каков наилучший подход для этого с использованием шаблона ввода-вывода DI и .NetCore?
Я попытался установить все соединения в объекте DAL и указать идентификатор соединения при вызове метода.У меня есть возможность иметь разные классы для каждого, но я думаю, что это излишне.
Итак, давайте предположим, что у меня есть это в appsettings.json
"DatabaseMetaConfiguration": {
"MappingDb": {
"DNS": "pgc.app.corp.acme.com",
"Database": "mappings",
"User": "mappings_user",
"Pass": "111",
"SSL": "SSL Mode=Prefer; Trust Server Certificate=true"
},
"StatusDb": {
"DNS": "pgc.app.corp.acme.com",
"Database": "status",
"User": "status_user",
"Pass": "222",
"SSL": "SSL Mode=Prefer; Trust Server Certificate=true"
},
"MasterDb": {
"DNS": "pgc.app.corp.acme.com",
"Database": "master",
"User": "master_user",
"Pass": "333",
"SSL": "SSL Mode=Prefer; Trust Server Certificate=true"
},
"BookDb": {
"DNS": "pgc.app-books.corp.acme.com",
"Database": "book",
"User": "book_user",
"Pass": "444",
"SSL": "SSL Mode=Prefer; Trust Server Certificate=true"
}
}
Затем классы параметров POCO:
public class PostgreSqlDatabaseMetaConfigurations : Dictionary<string, PostgreSqlDatabaseMetaConfiguration> { }
public class PostgreSqlDatabaseMetaConfiguration
{
public string Database { get; set; }
public string User { get; set; }
public string Pass { get; set; }
public string DNS { get; set; }
public string SSL { get; set; }
public int Timeout { get; set; }
public int CommandTimeout { get; set; }
public string ConnectionString { get { [...] } }
}
И фактический класс DAL:
public class PostgreSqlManager : IDisposable, ISqlManager
{
private readonly Dictionary<string, NpgsqlConnection> _connections;
private readonly ILogger<PostgreSqlManager> _logger;
public PostgreSqlManager(IOptionsMonitor<PostgreSqlDatabaseMetaConfigurations> optionsAccessor, ILogger<PostgreSqlManager> logger)
{
_logger = logger;
var dbConfigurations = optionsAccessor.CurrentValue;
if (dbConfigurations == null || !dbConfigurations.Any())
_logger.LogWarning("No connections configured!");
// Create a dictionary of connections, indexed by the connection names
_connections = dbConfigurations.ToDictionary(c => c.Key, c => new NpgsqlConnection(c.Value.ConnectionString));
}
// So, a sample method would be...
public async Task<long> ExecuteScalarAsync(string connectionId, string commandText, List<DbParameter> parameters = null, CommandType commandType = CommandType.Text)
{
using (var command = GetDbCommand(_connections[connectionId], commandText, parameters, commandType))
{
try
{
await command.Connection.OpenAsync();
return (Int64)await command.ExecuteScalarAsync().ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception on ExecuteScalarAsync({0})", commandText);
throw;
}
finally
{
command.CloseCommand();
}
}
}
}
Наконец, в ConfigureServices у меня есть следующие строки:
services.AddSingleton<ISqlManager, PostgreSqlManager>();
services.Configure<PostgreSqlDatabaseMetaConfigurations>(configuration.GetSection("DatabaseMetaConfiguration"));
(извините за большие куски кода,Я хотел, чтобы это было ясно.)
Теперь, если я хочу использовать класс обслуживания DAL, мне нужно добавить ISqlManager
в мой контроллер.Затем при каждом вызове метода мне нужно указать, какое соединение я хочу.
Теперь вот мой вопрос.Если я заранее знаю, какое соединение мне нужно в каждом классе контроллеров, как я могу указать его, чтобы каждый контроллер использовал соединение, которое, как я знаю, ему понадобится?
Еще лучше, могу ли я установить несколько разных экземпляров класса DALв DI-контейнер, каждый с различным соединением, и пусть каждый класс контроллера решает, какой из них использовать?
Спасибо за чтение.