EntityFramework核心自动迁移

时间:2016-09-16 08:07:58

标签: entity-framework asp.net-core entity-framework-core

是否有任何代码可以在asp.net核心项目的Entity Framework core code first中执行自动迁移?

我只是在MVC4 / 5中添加

Database.SetInitializer(new MigrateDatabaseToLatestVersion<AppDbContext, MyProject.Migrations.Configuration>());
public Configuration() {
          AutomaticMigrationsEnabled = true;
        }

这节省了实体更改的时间

10 个答案:

答案 0 :(得分:25)

EF核心不支持 automatic migrations。所以你必须手动完成。

  

从自动迁移的角度来看,我们不是   计划在EF Core中实现它,因为经验显示了代码库   迁移是一种更易于管理的方法。

您可以在此处阅读全文:Not to implement Automatic Migrations

答案 1 :(得分:24)

您可以在context.Database.Migrate()

中致电Startup.cs

例如:

using (var context = new MyContext(...))
{
    context.Database.Migrate();
}

答案 2 :(得分:15)

这是他们在IdentityServer4 http://identityserver.io

中执行此操作的方式
public void ConfigureServices(IServiceCollection services)
{
    var connectionString = Configuration.GetConnectionString("DefaultConnection");
    var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

    // Add framework services.
    services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(connectionString));
    ...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    // this will do the initial DB population
    InitializeDatabase(app);
}

private void InitializeDatabase(IApplicationBuilder app)
{
    using (var scope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
    {
        scope.ServiceProvider.GetRequiredService<ApplicationDbContext>().Database.Migrate();
        scope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();
        ...
    }
}

答案 3 :(得分:11)

EF Core不支持自动迁移。迁移是必要的创造手。要自动应用所有现有的手工迁移,需要在DbContext中添加以下代码:

public sealed class MyDbContext : DbContext
{
  private static readonly bool[] _migrated = { false };

  public MyDbContext( DbContextOptions<MyDbContext> options ) : base( options )
  {
    if ( !_migrated[0] )
      lock ( _migrated )
        if ( !_migrated[0] )
        {
          Database.Migrate(); // apply all migrations
          _migrated[0] = true;
        }
  }
}

它不优雅,但有效。

更新EFCore 2.1:

public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateWebHostBuilder(args).Build();

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;

            try
            {
                var context = services.GetRequiredService<MyDbContext>();
                context.Database.Migrate(); // apply all migrations
                SeedData.Initialize(services); // Insert default data
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred seeding the DB.");
            }
        }

        host.Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

答案 4 :(得分:3)

遵循Microsoft的文档

https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro

如果您正在使用依赖注入,首先需要设置静态类 Data / DbInitializer.cs 并添加以下代码:

public static class DbInitializer
{
    public static void Initialize(ApplicationDbContext context)
    {
        context.Database.Migrate();

        // Add Seed Data...
    }
}

请注意,这也是您可以添加种子数据的地方。

接下来,在Program.cs文件中,添加以下代码

public static void Main(string[] args)
    {
        var host = BuildWebHost(args);

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;
            try
            {
                var environment = services.GetRequiredService<IHostingEnvironment>();

                if (!environment.IsDevelopment())
                {
                    var context = services.GetRequiredService<ApplicationDbContext>();
                    DbInitializer.Initialize(context);
                }
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred while seeding the database.");
            }
        }

        host.Run();
    }

在我的情况下,我正在检查环境以确保我处于开发状态,因此我可以控制迁移/更新。但是,在生产中,我希望它们能够自动进行持续集成。正如其他人所提到的,这可能不是最佳实践,但对于小型项目,它的效果很好。

答案 5 :(得分:1)

我的自动迁移代码Asp Net Core 2.0.7。

    // startup.cs
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        // configure app

        SeedData.Initialize(app.ApplicationServices);
    }       

    // dbInitializer.cs
    public static class SeedData
    {
        public static void Initialize(IServiceProvider serviceProvider)
        {
            using (var serviceScope = serviceProvider.CreateScope())
            {
                var context = serviceScope.ServiceProvider.GetService<ApplicationDbContext>();

                // auto migration
                context.Database.Migrate();

                // Seed the database.
                InitializeUserAndRoles(context);
            }
        }

        private static void InitializeUserAndRoles(ApplicationDbContext context)
        {
            // init user and roles  
        }
    }

答案 6 :(得分:1)

Frank Odoom 的答案在 .net 5 中甚至在 4 年后仍然有效,但它不是在运行时调用迁移的预期上下文......而且,它似乎从来都不是,因为它要求我们使用 DbContextOptions 来模拟 DbContext文档明确指出:

"The options to be used by a DbContext. You normally override OnConfiguring(DbContextOptionsBuilder) or use a DbContextOptionsBuilder to create instances of this class and it is not designed to be directly constructed in your application code."

这是我的建议:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
       // database provider is configured before runtime migration update is applied e.g:
       optionsBuilder.UseSqlServer(ConnectionString);
       Database.Migrate();
}

编辑: 如果您在同一个项目中使用多个 DBContext,我的建议实际上很糟糕……它会多次迁移数据库。这很可能不会破坏任何东西,但会大大减慢启动速度。

答案 7 :(得分:0)

我最好的建议是不要使用自动迁移。手动添加迁移并避免批量迁移并坚持使用手动迁移的最佳做法总是更好

自动迁移不是一种神奇的工具,有时您可能希望在迁移中添加一些额外的更改。您只能通过手动迁移来完成。

要启用迁移,请在程序包管理器控制台中键入“enable-migrations”

通过这种方式,您可以完全控制升级或降级数据库,还可以轻松跟踪迁移。

在包管理器控制台中只需要三个简单的步骤。

1)add-migrations [迁移的某个名称]

2)为更改生成迁移,您可以查看它们,也可以       对其进行更改

3)update-database现在已完成迁移。

处理迁移不那么痛苦!

答案 8 :(得分:0)

您可以在数据库上下文构造函数中调用Database.Migrate()

答案 9 :(得分:0)

如果模型发生了很大变化,并且您管理的是中型团队,那么至少在开发阶段,迁移会比解决方案带来更多的问题。 我发布了一个具有.net核心EFCore.AutomaticMigrations-https://www.nuget.org/packages/EFCore.AutomaticMigrations/的自动迁移的nuget程序包,因此不再需要手动迁移。

您可以像下面这样直接在Program类中调用:

 public static void Main(string[] args)
    {
        var host = CreateWebHostBuilder(args);

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;
            var loggerFactory = services.GetRequiredService<ILoggerFactory>();
            var logger = loggerFactory.CreateLogger<Program>();
            try
            {
                var environment = services.GetRequiredService<IWebHostEnvironment>();

                if (environment.IsDevelopment())
                {
                    var context = services.GetRequiredService<ApplicationContext>();
                    MigrateDatabaseToLatestVersion.ExecuteAsync(context).Wait();
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "An error occurred creating/updating the DB.");
            }
        }

        host.Run();
    }