使用MVC中的Entity Framework Code First更新现有数据库

Jac*_*ack 10 sql-server asp.net-mvc entity-framework updatemodel ef-code-first

在我的MVC应用程序中,我使用了Entity Framework 6并使用代码优先方法创建了数据库.经过一段时间后,我通过添加新列并删除了一些列来更新其中一个实体类.为了将这些更改反映到数据库,我按照以下步骤操作:

  1. 删除了项目中的迁移文件夹.
  2. 删除了数据库中的__MigrationHistory表.
  3. 然后在程序包管理器控制台中运行以下命令:
    Enable-Migrations -EnableAutomaticMigrations -Force

  4. 在配置文件中添加以下行:
    AutomaticMigrationsEnabled = true;
    AutomaticMigrationDataLossAllowed = true;

  5. 运行:
    Add-Migration Initial

  6. 最后,运行:
    Update-Database -Verbose

但是,我遇到一个错误"数据库中已经有一个名为'xxx'的对象."

为了摆脱这个问题,我在第5步之后创建的初始文件中注释Up方法中的代码.这可以防止错误,但数据库中没有任何更改(更新的实体表保持不变).哪里出错了?在此先感谢您的帮助.

这是我在migration.cs文件中注释的Up方法:

    public override void Up()
    {
        CreateTable(
            "dbo.City",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    Name = c.String(nullable: false),
                    RegionID = c.Int(nullable: false),
                })
            .PrimaryKey(t => t.ID)
            .ForeignKey("dbo.Region", t => t.RegionID)
            .Index(t => t.RegionID);

        CreateTable(
            "dbo.Multiplier",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    Status = c.Int(nullable: false),
                    Term = c.Int(nullable: false),
                    CityID = c.Int(nullable: false),
                    WhoIsOnline = c.String(nullable: false),
                    UserId = c.String(nullable: false),
                    InstituteName = c.String(nullable: false),
                    InstituteStatusID = c.Int(nullable: false),
                    InstituteAccreditationDate = c.DateTime(nullable: false),
                    Address = c.String(nullable: false),
                    Phone = c.String(nullable: false),
                    Fax = c.String(),
                    Email = c.String(nullable: false),
                    EurodeskEmail = c.String(nullable: false),
                    WebSite = c.String(),
                    ContactName = c.String(nullable: false),
                    ContactSurname = c.String(nullable: false),
                    ContactJobTitle = c.String(),
                    ContactAssignmentDate = c.DateTime(),
                    ContactWorkingStart = c.String(),
                    ContactWorkingkEnd = c.String(),
                    ContactPhone = c.String(),
                    ContactMobile = c.String(nullable: false),
                    ContactEmail = c.String(nullable: false),
                    ContactCityID = c.Int(nullable: false),
                    LegalRepresentativeName = c.String(nullable: false),
                    LegalRepresentativeSurname = c.String(nullable: false),
                })
            .PrimaryKey(t => t.ID)
            .ForeignKey("dbo.City", t => t.CityID)
            .ForeignKey("dbo.InstituteStatus", t => t.InstituteStatusID)
            .Index(t => t.CityID)
            .Index(t => t.InstituteStatusID);

        CreateTable(
            "dbo.InstituteStatus",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    Name = c.String(nullable: false),
                })
            .PrimaryKey(t => t.ID);

        CreateTable(
            "dbo.TrainingParticipant",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    TrainingID = c.Int(nullable: false),
                    ParticipantID = c.Int(nullable: false),
                    Multiplier_ID = c.Int(),
                })
            .PrimaryKey(t => t.ID)
            .ForeignKey("dbo.Participant", t => t.ParticipantID)
            .ForeignKey("dbo.Training", t => t.TrainingID)
            .ForeignKey("dbo.Multiplier", t => t.Multiplier_ID)
            .Index(t => t.TrainingID)
            .Index(t => t.ParticipantID)
            .Index(t => t.Multiplier_ID);

        CreateTable(
            "dbo.Participant",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    Name = c.String(nullable: false),
                    Surname = c.String(nullable: false),
                    MultiplierID = c.Int(nullable: false),
                })
            .PrimaryKey(t => t.ID)
            .ForeignKey("dbo.Multiplier", t => t.MultiplierID)
            .Index(t => t.MultiplierID);

        CreateTable(
            "dbo.Training",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    Name = c.String(nullable: false),
                    Date = c.DateTime(nullable: false),
                    CityID = c.Int(nullable: false),
                })
            .PrimaryKey(t => t.ID)
            .ForeignKey("dbo.City", t => t.CityID)
            .Index(t => t.CityID);

        CreateTable(
            "dbo.Region",
            c => new
                {
                    ID = c.Int(nullable: false, identity: true),
                    Name = c.String(nullable: false),
                })
            .PrimaryKey(t => t.ID);

    }
Run Code Online (Sandbox Code Playgroud)


这是migration.cs文件中的Down方法:

    public override void Down()
    {
        DropForeignKey("dbo.City", "RegionID", "dbo.Region");
        DropForeignKey("dbo.TrainingParticipant", "Multiplier_ID", "dbo.Multiplier");
        DropForeignKey("dbo.TrainingParticipant", "TrainingID", "dbo.Training");
        DropForeignKey("dbo.Training", "CityID", "dbo.City");
        DropForeignKey("dbo.TrainingParticipant", "ParticipantID", "dbo.Participant");
        DropForeignKey("dbo.Participant", "MultiplierID", "dbo.Multiplier");
        DropForeignKey("dbo.Multiplier", "InstituteStatusID", "dbo.InstituteStatus");
        DropForeignKey("dbo.Multiplier", "CityID", "dbo.City");
        DropIndex("dbo.Training", new[] { "CityID" });
        DropIndex("dbo.Participant", new[] { "MultiplierID" });
        DropIndex("dbo.TrainingParticipant", new[] { "Multiplier_ID" });
        DropIndex("dbo.TrainingParticipant", new[] { "ParticipantID" });
        DropIndex("dbo.TrainingParticipant", new[] { "TrainingID" });
        DropIndex("dbo.Multiplier", new[] { "InstituteStatusID" });
        DropIndex("dbo.Multiplier", new[] { "CityID" });
        DropIndex("dbo.City", new[] { "RegionID" });
        DropTable("dbo.Region");
        DropTable("dbo.Training");
        DropTable("dbo.Participant");
        DropTable("dbo.TrainingParticipant");
        DropTable("dbo.InstituteStatus");
        DropTable("dbo.Multiplier");
        DropTable("dbo.City");
    }
Run Code Online (Sandbox Code Playgroud)

Chr*_*att 13

你为什么要做1-4步?那是你出错的地方.如果您有一个以前生成的数据库而您只是对模式进行了更改,那么只需生成一个迁移并应用它.通过执行步骤1-4,您可以有效地撤消实体框架对此数据库的了解,并最终使用现有数据库实现代码优先.此时,您必须手动更改架构或让实体框架将其彻底清除并重新开始.

至于回到可以再次应用迁移的状态,您可以在正确的轨道上生成迁移并清空Up方法.但是,您需要针对应用程序的先前状态(即与当前数据库匹配的状态)执行此操作.否则,Entity Framework将生成包含代码更改的create table.所以要遵循的步骤是:

  1. 将代码还原到开始修改POCO之前的位置.
  2. 生成迁移.
  3. 删除Up方法中的所有内容
  4. 应用迁移 update-database
  5. 重新应用您对POCO所做的更改.
  6. 生成另一个迁移(现在应该只添加/更改列语句而不是创建表)
  7. 应用迁移.

在那之后,你应该再次去.然后,下次更改代码时,只需按照步骤5和6进行操作.


小智 5

我有这个确切的问题.似乎值得注意的是,有一些命令可以帮助解决这种情况,即-IgnoreChanges和-Force标志.

我正在从一个multi-dbContext修剪到单个dbContext应用程序.正如您可以猜测表已经存在,但单个上下文中没有新的表在第二个上下文中维护.

它实际上非常简单(虽然2天的搜索答案无济于事导致我阅读了EF Code First Migrations命令行和包管理器 ......)以下是我处理它的方法.

您可以删除SQL中的迁移文件夹和_Migrations表...这将导致您需要使用以下内容:启用 - 迁移 - 强制

但你应该能够从这里拿起而不采取严厉的措施:

  1. 添加迁移"重置"-IgnoreChanges -Force(强制忽略模型/类中可能存在的更改 - 适合现有数据库入门)
  2. Update-Database(只写迁移行作为基础)
  3. 添加迁移"AddMyMigrationsToThisDb"-Force(强制迭代代码中的对象模型以获取更改)
  4. 更新数据库

现在,您应该回到正轨,只使用Add-Migration和Update-Database而不需要额外的标志.