Добавить миграцию с другой сборкой

Я делаю проект в ASP.NET CORE 1.0.0, и я использую EntityFrameworkCore. У меня есть отдельные сборки, и моя структура проекта выглядит следующим образом:

ProjectSolution
   -src
      -1 Domain
         -Project.Data
      -2 Api
         -Project.Api

В моем Project.Api есть класс Startup

public void ConfigureServices(IServiceCollection services)
    {            
        services.AddDbContext<ProjectDbContext>();

        services.AddIdentity<IdentityUser, IdentityRole>()
                .AddEntityFrameworkStores<ProjectDbContext>()
                .AddDefaultTokenProviders();
    }

DbContext находится в моем проекте Project.Data

public class ProjectDbContext : IdentityDbContext<IdentityUser>
{
    public ProjectDbContext(DbContextOptions<ProjectDbContext> options) : base(options)
    {

    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {

        var builder = new ConfigurationBuilder();
        builder.SetBasePath(Directory.GetCurrentDirectory());
        builder.AddJsonFile("appsettings.json");
        IConfiguration Configuration = builder.Build();

        optionsBuilder.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection"));
        base.OnConfiguring(optionsBuilder);
    }
}

Когда я пытаюсь выполнить первоначальную миграцию, я получаю эту ошибку:

"Ваш целевой проект" Project.Api "не соответствует вашей сборке миграции" Project.Data ". Либо измените целевой проект, либо измените сборку миграции. Измените сборку миграции с помощью DbContextOptionsBuilder. Например. options.UseSqlServer(connection, b => b.MigrationsAssembly("Project.Api")). По умолчанию сборка миграции является сборкой, содержащей DbContext. Измените целевой проект на проект миграции с помощью раскрывающегося списка проекта консоли диспетчера пакетов по умолчанию или выполнив "dotnet ef" из каталога, в котором находится проект миграции. "

После того, как я увидел эту ошибку, я попытался выполнить эту команду, расположенную в Project.Api:

dotnet ef --startup-project../Project.Api --assembly "../../1 Data/Project.Data" migrations add Initial

и я получил эту ошибку:

"Unexpected value '../../1 Domain/Project.Data' for option 'assembly'"

Я не знаю, почему я получаю эту ошибку, когда пытаюсь выполнить команду с параметром -assembly.

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

У кого-нибудь были похожие проблемы?

Ответ 1

Все команды EF имеют эту проверку:

if (targetAssembly != migrationsAssembly) 
       throw MigrationsAssemblyMismatchError;

targetAssembly= целевой проект, над которым вы работаете. В командной строке это проект в текущем рабочем каталоге. В консоли диспетчера пакетов это любой проект, выбранный в раскрывающемся списке в правом верхнем углу окна окна.

migrationsAssembly= сборка, содержащая код для миграции. Это настраивается. По умолчанию это будет сборка, содержащая DbContext, в вашем случае, Project.Data.dll. Как следует из сообщения об ошибке, у вас есть два варианта разрешения этого

1 - Измените целевую сборку.

cd Project.Data/
dotnet ef --startup-project ../Project.Api/ migrations add Initial

// code doesn't use .MigrationsAssembly...just rely on the default
options.UseSqlServer(connection)

2 - Измените сборку миграции.

cd Project.Api/
dotnet ef migrations add Initial

// change the default migrations assembly
options.UseSqlServer(connection, b => b.MigrationsAssembly("Project.Api"))

Ответ 2

У меня была такая же проблема, пока я не заметил, что на верхней панели консоли диспетчера пакетов => "Проекты по умолчанию" должен был быть "Project.Data", а не "Project.API".

Как только вы выберете "Project.Data" из выпадающего списка и запустите миграцию, все будет в порядке.

default project selection

Ответ 3

Используя EF Core 2, вы можете легко отделить ваш веб-проект от вашего проекта Data (DbContext). На самом деле, вам просто нужно реализовать интерфейс IDesignTimeDbContextFactory. Согласно документам Microsoft, IDesignTimeDbContextFactory является:

Фабрика для создания производных экземпляров DbContext. Реализуйте этот интерфейс, чтобы включить службы времени разработки для типов контекста, которые не имеют общедоступного конструктора по умолчанию. Во время разработки производные экземпляры DbContext могут быть созданы для того, чтобы обеспечить особые возможности во время разработки, такие как Миграции. Службы времени разработки автоматически обнаружат реализации этого интерфейса, которые находятся в сборке запуска или в той же сборке, что и производный контекст.

В нижнем фрагменте кода вы можете увидеть мою реализацию DbContextFactory, которая определена внутри моего проекта данных:

public class DbContextFactory : IDesignTimeDbContextFactory<KuchidDbContext>
{
    public KuchidDbContext CreateDbContext(string[] args)
    {
        var configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json")
            .Build();

        var dbContextBuilder = new DbContextOptionsBuilder<KuchidDbContext>();

        var connectionString = configuration.GetConnectionString("Kuchid");

        dbContextBuilder.UseSqlServer(connectionString);

        return new KuchidDbContext(dbContextBuilder.Options);
    }
}

Теперь я могу инициализировать миграцию EF, установив свой веб-проект в качестве проекта автозагрузки и выбрав свой проект данных в консоли диспетчера пакетов.

Add-Migration initial

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

Ответ 4

Я столкнулся с той же проблемой и нашел this

Вы пытались выполнить миграцию в библиотеке классов? Я тоже. Оказывается, это еще не поддерживается, поэтому нужно обойти его.

EDIT: я нашел решение на этот git repo

Ответ 5

В настоящее время я думаю, что EF поддерживает только добавление миграции в проекты, еще не находящиеся в библиотеках классов.

И только примечание стороны для кого-либо еще, кто хочет добавить миграции в определенную папку внутри вашего проекта:

EF CLI еще не поддерживает это. Я попробовал --data-dir, но это не сработало.

Единственное, что работает, это использовать консоль диспетчера пакетов:

  • Выберите проект по умолчанию
  • use -OutputDir command parameter,.e.g., Add-Migration InitConfigurationStore -OutputDir PersistedStores/ConfigurationStore команда выведет mgiration в папку PersistedStores/ConfigurationStore в моем проекте.

Обновления от 10/12/2017

public void ConfigureServices(IServiceCollection services)
{
    ...

    string dbConnectionString = services.GetConnectionString("YOUR_PROJECT_CONNECTION");
    string assemblyName = typeof(ProjectDbContext).Namespace;

    services.AddDbContext<ProjectDbContext>(options =>
        options.UseSqlServer(dbConnectionString,
            optionsBuilder =>
                optionsBuilder.MigrationsAssembly(assemblyName)
        )
   );

   ...
}

Ответ 6

(ASP.NET Core 2+)

Была такая же проблема. Вот что я сделал:

  1. Ссылка на проект, содержащий DbContext (Project.A), из проекта, который будет содержать миграции (Project.B).

  2. Переместить существующие миграции из Project.A в Project.B (Если у вас нет миграций - сначала создайте их)

  3. Настройте сборку миграции внутри Project.A

options.UseSqlServer( ConnectionString, x => x.MigrationsAssembly("Project.B"));

Предположим, что ваши проекты находятся в одной родительской папке:

  1. dotnet ef migrations add Init --project Project.B -c DbContext

Миграции теперь идут в Project.B

Источник: Microsoft

Ответ 7

Add-Migration NewMigration -Project MyApp.Migrations

Ответ 8

Я столкнулся с подобной проблемой, хотя ответы кажутся прямыми, так как они не работают. Мой ответ похож на @Ehsan Mirsaeedi, с небольшим изменением в классе DbContextFactory. Вместо добавления имени сборки миграции в классе Startup API, я упомянул класс DbContextFactory, который является частью проекта Data (библиотеки классов).

public class DbContextFactory : IDesignTimeDbContextFactory<KuchidDbContext>
{
   public KuchidDbContext CreateDbContext(string[] args)
   {
       var configuration = new ConfigurationBuilder()
          .SetBasePath(Directory.GetCurrentDirectory())
          .AddJsonFile("appsettings.json")
          .Build();

       var dbContextBuilder = new DbContextOptionsBuilder<KuchidDbContext>();

       var connectionString = configuration.GetConnectionString("connectionString");

       var migrationAssemblyName= configuration.GetConnectionString("migrationAssemblyName");

       dbContextBuilder.UseSqlServer(connectionString, o => o.MigrationAssembly(migrationAssemblyName));

       return new KuchidDbContext(dbContextBuilder.Options);
   }
}

Для работы расширений SetBasePath и AddJsonFile вам понадобятся "Microsoft.Extensions.Configuration" и "Microsoft.Extensions.Configuration.Json".

Примечание: я чувствую, что это всего лишь обходной путь. Он должен забрать DbContextOptions из класса запуска, так как это не так. Я думаю, что есть определенная проблема с проводкой.

Ответ 9

Решение от @Kaloyan Drenski сработало для меня. Asp.net Core 2.2

Ответ 10

Для всех вас, у кого есть несколько проектов запуска.

Обратите внимание, что вам нужно установить целевой проект как стартовый проект - Project.Api (из примера вопроса) должен быть стартовым проектом.

Надеюсь, что это поможет кому-то :)