ChatGPT解决这个技术问题 Extra ChatGPT

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

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

我已经看到提到有一个 API 可以使用 DbMigration 类在运行时执行这些迁移,但我找不到任何具体示例。

理想情况下,我希望每个数据库更改都有一个 DbMigration 文件,并且这些更改会在应用程序从当前版本到最新版本启动时自动应用。


d
devdigital

有一个 Database Initializer 可用于在启动时迁移到最新版本(或者更好的是,dbinitializer 将在第一次访问 db 时启动),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


这段代码将添加到哪里?这可以包含在条件语句中以检查 web.config 文件中的应用程序设置吗?以便在开发过程中可以跳过此代码?那么 web.config 转换会在发布发布版本时启用它吗?
如果您需要有条件地为配置属性设置初始化程序,那么更好的方法是使用 EF4.3 的功能。请参阅这篇文章 msdn.microsoft.com/en-US/data/jj556606(“数据库初始化程序”部分),将其与转换结合使用,您就可以设置
在此处了解更多信息:msdn.microsoft.com/en-us/data/jj591621.aspx#initializer 对于那些对自动迁移和数据库架构更新持谨慎态度并认为手动编辑脚本更安全的人...验证您是否有备份并首先对其进行测试以备不时之需清酒!!
我在更新 this question 时扩展了该主题,欢迎同行评审
此解决方案意味着应用程序有权更改架构。我认为这在应用程序仅限于数据操作的 prod 环境中不太可能。我想知道是否可以使用 dotnet CLI(从管理员帐户或通过提供凭据)从编译的 DLL 运行迁移
d
devdigital

这也有效:

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

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

您也可以致电:

migrator.GetPendingMigrations();

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


这里的变量 database 是什么?
在这种情况下,只是一个具有 ConnectionString 和 ProviderName 属性的 DTO。它不是框架的一部分。
如果我使用这种方法,我应该在我的 dbContext 创建上使用什么初始化程序?
在您的 DbContext 构造函数中,只需执行以下操作: Database.SetInitializer(null);
这对我有用,甚至删除了 new DbConnectionInfo 部分。谢谢!
W
Worthy7

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

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

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

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

https://i.stack.imgur.com/kysUI.png

指南: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/

祝你好运!


只是一个扩展的评论,因为我现在年纪大了,也更聪明了。通常你不想在生产服务器上自动执行迁移。理想情况下,您生成一个 SQL 脚本来进行迁移,验证它是否符合您的要求,然后在发布/部署您的应用程序时在生产数据库上运行该脚本。这是做到这一点的“标准”方式。
这在发布到 File System 时不可用
P
Panos Roditakis

我想控制哪些迁移在代码中显式运行,经过大量搜索后,我设法开发了以下技术,而无需 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);
}

问候。


L
LuTheZy

添加到所有已发布的答案。 Entity Framework 使用表: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 将运行尚未应用于数据库的迁移。