Могу ли я вносить зависимость в миграцию (с использованием первых кодов EF-Core)?

Я попытался ввести IConfiguration в перенос (в конструкторе) и получил исключение: "Без конструктора без параметров для этого объекта".

любой обходной путь?

Ответ 1

вы не можете, миграции должны быть в состоянии работать вне контекста вашего приложения.

Поскольку инструмент командной строки Entity-framework анализирует ваш код, но не запускает класс startup.cs.

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

дополнительный совет

Если это включает в себя много небольших/равных/ручных изменений. Лучший способ - создать файл миграции. Зачем? Таким образом, ваша миграция будет детерминированной: вы знаете, каков будет результат. Если в вашей миграции произошел сбой, просто и понятно, почему это можно и легко исправить.

Ответ 2

Есть способ сделать то, что вы хотите сделать. В моем сценарии я хотел бы использовать имя базы данных в строке подключения через DbContext. EF core 2.1.1 используется. Код изменен отсюда

Создайте пользовательский сервис MigrationsAssembly

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations.Internal;
using System;
using System.Reflection;

public class ContextAwareMigrationsAssembly : MigrationsAssembly
{
    private readonly DbContext context;

    public ContextAwareMigrationsAssembly(
        ICurrentDbContext currentContext,
        IDbContextOptions options,
        IMigrationsIdGenerator idGenerator,
        IDiagnosticsLogger<DbLoggerCategory.Migrations> logger) : base(currentContext, options, idGenerator, logger)
    {
        context = currentContext.Context;
    }

    /// <summary>
    /// Modified from http://weblogs.thinktecture.com/pawel/2018/06/entity-framework-core-changing-db-migration-schema-at-runtime.html
    /// </summary>
    /// <param name="migrationClass"></param>
    /// <param name="activeProvider"></param>
    /// <returns></returns>
    public override Migration CreateMigration(TypeInfo migrationClass, string activeProvider)
    {
        var hasCtorWithDbContext = migrationClass
                .GetConstructor(new[] { typeof(DbContext) }) != null;

        if (hasCtorWithDbContext)
        {
              var instance = (Migration)Activator.CreateInstance(migrationClass.AsType(), context);
              instance.ActiveProvider = activeProvider;
              return instance;
        }

        return base.CreateMigration(migrationClass, activeProvider);
    }
}

Замените службу IMigrationAssembly в вашем DbContext на ваш собственный класс

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.ReplaceService<IMigrationsAssembly, ContextAwareMigrationsAssembly>();
}

Затем вы можете добавить параметр DbContext в вашу миграцию.

public Migration20180801(DbContext context)
{
    DatabaseName = context.Database.GetDbConnection().Database;
}

В вашем случае, вы можете заменить все DbContext ссылки с IConfiguration и соответствующий экземпляр в CreateMigration переопределения.

Ответ 3

Если речь идет только о вашей строке подключения (не так ли?), Вы можете проверить этот ответ, который в основном предлагает этот код в вашем проекте запуска (не в вашем проекте миграции):

var myConnectionString = Configuration.GetConnectionString(myConnectionStringName);
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(
    myConnectionString ,
    x => x.MigrationsAssembly(myDbContextAssemblyName)));