在生产中使用实体框架(代码优先)迁移

问题描述 投票:0回答:6

我只是考虑在我们的项目中使用 EF 迁移,特别是在版本之间执行生产中的架构更改。

我已经提到有一个 API 可以使用

DbMigration
类在运行时执行这些迁移,但我找不到任何具体示例。

理想情况下,我希望每个数据库更改都有一个

DbMigration
文件,并且这些更改会在应用程序启动时自动应用,从当前版本到最新版本。

.net entity-framework ef-code-first entity-framework-migrations
6个回答
82
投票

有一个数据库初始化程序,您可以使用它在启动时迁移到最新版本(或者更好,dbinitializer 将在第一次数据库访问时启动),

MigrateDatabaseToLatestVersion
,您可以像这样使用它:

Database.SetInitializer<ObjectContext>(
    new MigrateDatabaseToLatestVersion<ObjectContext, Configuration>());

关于每次迁移只有一个文件,如果您启用自动迁移,您将在项目根目录的

Migrations
文件夹(默认情况下)中找到它们。

相关信息和示例,请参见:http://weblogs.asp.net/fredriknormen/archive/2012/02/15/using-entity-framework-4-3-database-migration-for-any-project。 ASPX


49
投票

这也有效:

var configuration = new MyDbContextConfiguration();
configuration.TargetDatabase = new DbConnectionInfo(
    database.ConnectionString, database.ProviderName);

var migrator = new DbMigrator(configuration);
migrator.Update();

您也可以致电:

migrator.GetPendingMigrations();

获取需要应用的迁移列表。


9
投票

由于您没有指定您使用的是哪个 Visual Studio 版本或数据库,我将在这里添加一个答案,说在带有 Microsoft SQL Server 的 VS2015 中,现在使用“发布”工具非常容易。

您无需费心使用您所说的 API。只需在本地完成工作,更改模型,应用迁移等,然后当您想要推送到发布/测试服务器时,请使用发布工具。

您可以选择在应用程序首次启动时将本地所做的任何迁移应用到远程服务器。

完成所有迁移并在本地完成所有操作(假设在您的开发环境中)后,即可发布(右键单击项目,单击“发布...”,勾选“执行代码优先迁移(在应用程序启动时运行)”复选框在“设置”选项卡下,然后它将在第一次访问应用程序时应用迁移(因此第一次会有短暂的延迟)。

指南: https://msdn.microsoft.com/en-us/library/dd465337(v=vs.110).aspx

我学到了这一切,因为我必须对 Windows 2012 服务器执行此操作: http://www.sherweb.com/blog/how-to-install-webdeploy-on-windows-server-2012/

祝你好运!


4
投票

我想控制哪些迁移在代码中显式运行,经过大量搜索后,我设法开发了以下技术,而不需要 DbConfiguration 类或启用自动迁移:

public static void RunMigration(this DbContext context, DbMigration migration)
{            
    var prop = migration.GetType().GetProperty("Operations", BindingFlags.NonPublic | BindingFlags.Instance);
    if (prop != null)
    {
        IEnumerable<MigrationOperation> operations = prop.GetValue(migration) as IEnumerable<MigrationOperation>;
        var generator = new SqlServerMigrationSqlGenerator();
        var statements = generator.Generate(operations, "2008");
        foreach (MigrationStatement item in statements)
            context.Database.ExecuteSqlCommand(item.Sql);
    }
}

如果我们有这样的迁移:

public class CreateIndexOnContactCodeMigration : DbMigration
{
    public override void Up()
    {
        this.CreateIndex("Contacts", "Code");
    }

    public override void Down()
    {
        base.Down();
        this.DropIndex("Contacts", "Code");
    }
}

我们会这样使用它:

using (var dbCrm = new CrmDbContext(connectionString))
{
    var migration = new CreateIndexOnContactCodeMigration();
    migration.Up();                
    dbCrm.RunMigration(migration);
}

问候。


1
投票

添加到所有已发布的答案中。实体框架使用表: dbo.__MigrationHistory 来跟踪已应用于数据库的所有迁移,以避免运行迁移,例如:插入数据或更改数据库架构。

如果您希望运行脚本,例如运行添加数据或更改数据库架构,您可以使用包管理器控制台创建一个空迁移,并通过新添加的迁移运行脚本。确保使用初始化程序来防止 EF 在每次运行时删除并重新创建数据库。

     public override void Up()
    {
        string directoryToSearchScripts = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..\\..\\"));

        string scriptFilePath = Directory.GetFiles(directoryToSearchScripts, "dummy-script.sql", SearchOption.AllDirectories).FirstOrDefault();
        if (!string.IsNullOrEmpty(scriptFilePath))
        {
            string fundsSqlScript = File.ReadAllText(scriptFilePath);
            Sql(fundsSqlScript);
        }
    }

    public override void Down()
    {
    }

当您发布应用程序并选中“执行代码优先迁移”选项时,EF 将运行尚未应用于数据库的迁移。


0
投票

在此对之前的答案进行澄清。

以下是如何使用它们以及放置代码的位置。

两种方法我都测试过,效果很好。

在 ASP.NET MVC 5 .NET FRAMEWORK 上测试

Global.asax

using MyApp.Models;
using System.Data.Entity;

namespace MyApp
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            Database.SetInitializer(new MigrateDatabaseToLatestVersion<ApplicationDbContext, Migrations.Configuration>());
        }
    }
}

Migrations\Configuration.cs

using MyApp.Models;
using System.Data.Entity.Migrations;

namespace MyApp.Migrations
{
    internal sealed class Configuration : DbMigrationsConfiguration<ApplicationDbContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;

            var migrator = new DbMigrator(this);
            migrator.Update();
        }
    }
}

希望它能为其他人节省一些时间。

© www.soinside.com 2019 - 2024. All rights reserved.