C# 现有数据库和新数据库的EntityFramework 6迁移?

C# 现有数据库和新数据库的EntityFramework 6迁移?,c#,entity-framework,migration,entity-framework-6,entityspaces,C#,Entity Framework,Migration,Entity Framework 6,Entityspaces,在我们的软件中,我们有一个拥有现有数据库的客户群。数据库当前通过EntitySpaces访问,但我们希望切换到EntityFramework(v6),因为不再支持EntitySpaces。我们还想利用迁移功能。自动迁移被禁用,因为我们只希望允许数据库迁移到管理员用户 我们从现有数据库生成了EF模型。这一切都运行得很好,但我们面临的真正问题是,以编程方式区分与模型匹配但尚未转换为EF(missing MigrationHistory table)的现有数据库和空/新数据库。转换现有数据库可以很好地

在我们的软件中,我们有一个拥有现有数据库的客户群。数据库当前通过EntitySpaces访问,但我们希望切换到EntityFramework(v6),因为不再支持EntitySpaces。我们还想利用迁移功能。自动迁移被禁用,因为我们只希望允许数据库迁移到管理员用户

我们从现有数据库生成了EF模型。这一切都运行得很好,但我们面临的真正问题是,以编程方式区分与模型匹配但尚未转换为EF(missing MigrationHistory table)的现有数据库和空/新数据库。转换现有数据库可以很好地进行空迁移,但对于新数据库,我们还需要包含完整模型的迁移。在迁移链中进行初始迁移总是与现有数据库冲突。当然,我们可以使用外部SQL脚本或ADO命令创建一个变通方法,创建并填充MigrationsHistory表。但这是我们想要避免的,因为我们的一些客户使用MsSql数据库,一些使用Oracle。所以我们真的希望保留EF提供的抽象层


有没有一种方法可以让EF通过基于代码的迁移来处理现有数据库和新数据库,而不返回到非EF的解决方法?

我最初的建议是捕获CreateTable引发的异常,但事实证明这是在另一个位置执行的,因此无法捕获到异常中

最简单的方法是使用Seed方法创建初始数据库(如果不存在)。要做到这一点

  • 从空白数据库开始,添加初始创建迁移并获取生成的SQL

    Add-Migration InitialCreate
    Update-Database -Script
    
  • 保存此脚本。您可以将其添加到资源、静态文件中,甚至可以将其保留在代码中,如果您真的愿意,这取决于您自己

  • 从InitialCreate迁移中删除所有代码(保留一个空的Up()和Down()函数)。这将允许运行空迁移,从而生成MigrationHistory表

  • 在迁移配置类中,可以使用
    context.Database.SqlQuery
    context.Database.ExecuteSqlCommand
    动态查询和执行SQL。测试主表是否存在,如果不存在,则执行上面生成的脚本

  • 这不是很整洁,但是实现起来很简单。好好测试它,因为Seed方法在每次迁移运行之后运行,而不仅仅是初始迁移。这就是为什么在做任何事情之前需要测试主表的存在性


    更复杂的方法是为迁移编写一个“CreateTableIfNotExists”方法,但这将涉及使用反射来调用DmbMigration类中的内部方法。

    感谢您的快速响应,Richard。尝试了你的方法,因为它看起来和我想要的完全一样。问题是,SQL的实际执行发生在EF中的其他地方的up/down方法之外。因此,在迁移代码中捕获SqlExceptions不会有帮助。甚至试图通过SQL(…)方法执行虚假的SQL命令。因此,必须在迁移之外,围绕Update(…)方法捕获异常。但在那里,您无法直接访问数据库。回到起点。嗯,我没意识到这一点。查看源代码,您应该能够创建自定义迁移操作,但这并不容易。迁移过程的内部都是“内部”的,但是您可以使用反射来创建“CreateTableIfNotExists”方法。不过,我不能帮助太多关于这一部分!用新建议更新了答案。谢谢更新。尽管您的建议最终会奏效,但我最终还是决定采用简单的sql脚本。虽然我需要一个单独的脚本为每一个数据库管理系统,仍然更少的痛苦在a。。。我将向EF团队推荐一些迁移前和迁移后的挂钩。干杯,伙计。有点离题,但FluentMigrator的模式。Exists表达式似乎是支持此用例所需的全部。EF似乎没有这个功能,我觉得很沮丧。