Подтвердить что ты не робот

EF multi-context с системой в стиле плагина. Как применять миграции во время выполнения?

У меня есть веб-приложение, которое должно быть составлено из серии плагинов в базовую инфраструктуру. Плагин - это скомпилированная DLL CLR + некоторые файлы содержимого, которые будут помещены в определенное место. Я использую Autofac для сканирования и регистрации типов из сборки, а также для причудливой маршрутизации для обслуживания контроллеров и активов. Но, поскольку каждая сборка плагина может содержать DbContext (по соглашению каждый будет использовать свою собственную базу данных), я не могу понять, что там делать.

Теперь я нашел много вещей о том, как использовать несколько контекстов, но все это требует знания того, что они будут во время разработки. Мое приложение не знает, какие контексты будут использоваться до выполнения.

То, что я ищу в идеале, - это какой-то способ сделать

ApplyMigrations<MyDbContext, MyDbConfiguration>();

Хотя я также должен был бы предоставить упорядоченный набор миграций для применения (при использовании явных миграций).

Где я сейчас спотыкаюсь, это стандартный

Database.SetInitializer(...)

так как это статический singleton, и каждый dbcontext в моей системе имеет свой собственный инициализатор.

4b9b3361

Ответ 1

Во-первых, из всех SetInitializer хранит объекты IDatabaseInitializer в словаре с ключом контекста Type as, поэтому теоретически многократные вызовы SetInitializer должны работать нормально.

С другой стороны, если это не сработает, другой вариант заключается в явной инициализации:

class YourContext : DbContext
{
    static YourContext()
    {
        Database.SetInitializer<YourContext>(YourMigratingDatabaseInitializer);
        using (var context = new YourContext())
        {
            context.Database.Initialize(false);
        }
    }

    public YourContext()
    {
        Database.SetInitializer<YourContext>(null);
    }
}

Ответ 2

Возможно, напишите интерфейс для начальной загрузки плагина, так что IPluginBootstrapper - отсюда вы можете передать ContainerBuilder для добавления в набор сервисов, которые предоставляет плагин, или вернуть встроенный контейнер, который плагин создает и объединяет на хосте, Таким образом, вы подталкиваете ответственность за все работы DB/миграции в каждый плагин, поэтому, когда вы заходите в новую dll, когда она загружается, она может запускать собственный путь обновления.

Другая альтернатива, возможно, у вас может быть раздел конфигурации, который определяет пару типов, поэтому Tuple и скажите Autofac найти все пары из них в каталоге плагинов, а затем вызвать SetInitializer с тем, что разрешено?