Автоматическая миграция EntityFramework Core

В моем проекте у меня есть 2 базы данных: одна - это моя настраиваемая база данных, а другая - это Microsoft Identity дает мне.

У меня есть такой код:

      public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
        ApplicationDbContext db, MyContext dbPSC)
{
     // ...

    db.Database.EnsureCreated();
    db.Database.Migrate();

    dbPSC.Database.EnsureCreated();
    dbPSC.Database.Migrate();
}

Я не знаю, когда будет миграция для миграции, верно? Затем у меня есть 2 ошибки:

  • миграция для вызывает ошибку каждый раз, когда приложение запускается, кроме первого раза
  • миграция для моего контекста кажется прекрасной

Что лучше всего использовать? Нужно ли вызывать миграцию для ApplicationDbContext?

Обновлять

Я удалил Migrationпапка. Затем изменил Startup.cs подобно

      public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
        ApplicationDbContext db, MyContext dbPSC)
{
     // ...

    db.Database.EnsureCreated();
    dbPSC.Database.EnsureCreated();
}

но когда приложение запускается, оно вообще не создает никаких таблиц. AuditDbContextпотому что я использую Audit.net

      public class MyContext : AuditDbContext
{
    public MyContext(DbContextOptions<MyContext> options) : base(options) { }

    public DbSet<Message> Messages { get; set; }
    public DbSet<AuditMessage> Audit_Messages { get; set; }

    #region Common Tables
    public DbSet<Country> Countries { get; set; }
    public DbSet<AuditCountry> Audit_Countries { get; set; }
    #endregion
    #region Seed
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Seed();
    }
    #endregion
}

Обновление #2

Я пробовал другое решение, но оно не работает. Решение состоит в том, чтобы использовать RelationalDatabaseCreator как следующий код

      public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
        ApplicationDbContext db, MyContext dbPSC)
{
     // ...

    db.Database.EnsureCreated();
    dbPSC.Database.EnsureCreated();
    RelationalDatabaseCreator databaseCreator = 
     (RelationalDatabaseCreator)context.Database.GetService<IDatabaseCreator>();
    databaseCreator.CreateTables();
}

Как Migrate(), при первом запуске приложение создает таблицы, но во второй раз вызывает ошибку, поскольку таблицы уже существуют в базе данных.

3 ответа

Проблема, скорее всего, в том, что вы звоните.

Из документов:

Обратите внимание, что этот API не использует миграции для создания базы данных. Кроме того, созданная база данных не может быть позже обновлена ​​с помощью миграций. Если вы ориентируетесь на реляционную базу данных и используете миграции, вы можете использовать метод DbContext.Database.Migrate(), чтобы обеспечить создание базы данных и применение всех миграций .

Итак, достаточно позвонить. Но я не виню вас, потому что это определенно вводящее в заблуждение название метода. Он многое делает, поскольку также создает схему БД, которая даже не основана на миграциях, а на текущем состоянии сущностей.

Но если вы не хотите использовать миграции для контекста Identity (потому что вы никоим образом не расширяете эти сущности), тогда верно обратное: вам не нужно вызывать, и вызова достаточно, чтобы убедиться, что схема создается впервые.

Нужен ли звонок?

Что касается наилучшей практики: некоторые разработчики вообще не любят вызывать из кода, потому что они считают, что такие операции схемы БД должны быть более контролируемыми (я уверен, вы знаете, что вы также можете выполнить обновление базы данных из CLI). Думаю, это зависит от ваших требований.

И что касается этого конкретного случая наличия отдельной базы данных для таблиц идентичности: они, скорее всего, никогда не изменятся, и особенно они не будут создавать миграцию сами по себе. Поэтому я бы сказал, что в этом нет необходимости, помимо того факта, что он может создавать и переносить базу данных, если она не существует (поэтому может быть полезно сохранить по этой причине; если вы используете миграции для этого контекста начать с).

Определение необходимости миграции

Вы можете использовать context.Database.GetPendingMigrationsAsync()чтобы проверить, нужна ли миграция. Как это делается, так это то, что в БД есть EFMigrationsHistory таблица, в которой хранятся идентификаторы примененных миграций, которые можно сравнить с файлами миграции в вашем решении.

Но я думаю, что большинство разработчиков не называют это GetPendingMigrationsAsync() (или версия синхронизации, если на то пошло), потому что вы можете просто позвонить, и если БД уже обновлена, никакого вреда не будет.

Прояснение миграции vs EnsureCreated

Я не уверен, сколько вы работали с EF, так что, скорее всего, это очевидно. Но используется, когда вы уже создали миграции, например, с помощью dotnet ef migrations add <migrationname>, который представляет собой способ постепенного изменения схемы базы данных с использованием подхода «сначала код».

Но если вы вообще не используете миграции, у вас есть очень простая схема, которую не нужно будет постепенно изменять с миграциями, и вы просто хотите убедиться, что БД существует со схемой, затем используйте только, и не использовать Migrate().

Проблема в том, что если вы измените свои объекты, база данных не обновится; если база данных уже существует, она ничего не делает. Так что тебе придется позвонить EnsureDeleted()с последующим обновлением схемы БД без миграций. Что, очевидно, влечет за собой потерю всех ваших данных. Вот почему миграции полезны. EnsureCreated() в основном используется, например, для интеграционного тестирования.


Кстати, вы можете использовать один и тот же контекст БД для ваших собственных таблиц и идентификаторов; Рискну сказать, что это «нормальный» способ работы с EF. Конечно, я полагаю, у вас могут быть свои конкретные причины для разлуки.

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

Но если вы не включите миграцию, то при каждом изменении вам придется заново создавать свою базу данных. Потому что «EnsureCreated» проверяет, существует ли уже база данных. Так что лучше включить миграции.

Итак, если вы не хотите ничего менять в ApplicationDbContext, вы можете использовать db.Database.EnsureCreated(); но если вы хотите что-то изменить или, возможно, вы хотите добавить больше полей в AspNetUsers и т. д., вам следует включить миграции и использовать db.Database.Migrate();

Кстати, вы также можете добавить свои собственные таблицы в ApplicationDbContext, если хотите.

Основываясь на ответах, которые вы мне прислали, я решил использовать миграцию. в Startup.cs Я добавил эти строки кода (dbPSC - это DbContext)

      dbPSC.Database.EnsureCreated();
if (dbPSC.Database.GetPendingMigrations().Count() > 0)
    dbPSC.Database.Migrate();
Другие вопросы по тегам