Несколько Серверов и БД, как поступить?
Есть как минимум 4 разных сервера и в десятки раз больше одинаковых (!) баз данных.
На 1 из серверов есть "системная" база, пускай будет xyz, из которой нужно взять данные, обработать их и положить туда, куда будет указано в таблице xyz.abc (есть столбцы ServerName, DbName).
Вопрос: как правильно поступать и работать с EF Core в такой ситуации?
После выборки из xyz.abc данные группируются по серверу и бд.
Пока есть: 2 разных DbContext'a: 1 - только для xyz БД, чтобы ходить туда за данными (наследуется несколькими DbContext'ами в Infrastructure сборках), 2 - для остальных баз и серверов, чтобы управлять данными на них (тоже наследуются в Infrastructure сборках).
Пока примерно реализовал это так:
- В каждой сборке в Infrastructure слое (сборок может быть несколько, у каждой свои DbContext'ы с разными данными) добавляются 2 DbContext'a: 1.1) Для основного сервера и базы
xyz(например товары), 1.2) для любых других серверов и бд, где есть какие-то таблицы связанные с товарами (соответственно, что в другой сборке будет DbContext дляxyz.abc2, где будут не товары, а заказы, например, но сервер и БД такой же); - В appsettings.json указывается формат строки для подключения (Server={0};Database={1}...)
- В фабрике (для каждого Infrastructure слоя будет своя) получаю из настроек формат строки для подключения, потом при вызове
CreateScopeсобираю строку и устанавливаю в DbContext; - Создаю в
CreateScopeUnitOfWork, который и отдаю клиентскому коду;
Код:
//Фабрика
public abstract class GisDbConnectorFactory<TDbContext> : IGisDbConnectorFactory
where TDbContext : DbContext
{
private readonly IDbContextFactory<TDbContext> dbContextFactory;
private readonly string connectionStringFormat;
private const string GisConnectionStringFormatName = "GisConnectionStringFormat";
public GisDbConnectorFactory(IDbContextFactory<TDbContext> dbContextFactory, IConfiguration configuration)
{
this.dbContextFactory = dbContextFactory;
connectionStringFormat = configuration.GetConnectionString(GisConnectionStringFormatName)!;
}
public IUnitOfWork<int> CreateScope(ServerGroup server)
{
var connectionString = string.Format(connectionStringFormat, server.ServerName, server.DbName);
var context = dbContextFactory.CreateDbContext();
context.Database.SetConnectionString(connectionString);
return new BaseUnitOfWork<TDbContext, int>(context);
}
}
Но вопрос еще в том, что через уже созданный в CreateScope DbContext нужно вызывать хранимые процедуры. Держать их в Application слое как-то не комильфо, нужно как-то запрятать их под сервис (интерфейс). Как это лучше сделать? Объединить IUnitOfWork + Свой сервис под общий интерфейс и отдавать клиенту его, а потом на клиенте уже вызывать то, что нужно? (например:
interface IRuStack
{
IUnitOfWork<int> UnitOfWork { get; }
IMySuperService Service { get; }
}
который и будет отдаваться клиентскому коду из CreateScope).
Или есть варианты лучше и правильнее?
Использую .net 7