实体框架迁移更新 - 数据库成功但未添加数据库列

时间:2014-06-03 05:42:10

标签: sql-server entity-framework ef-migrations

我在VS2012中使用Entity Framework和SQL Server 2008 R2。我启用了迁移,并且我将一个字符串字段(即DropboxUrl)添加到我的一个数据库类(即设计)中。

// Design.cs

public class Design
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public Guid Id { get; set; }

        [StringLength(Constants.DESIGN_NAME_MAX_LENGTH)]
        public string Name { get; set; }

        [StringLength(Constants.DESIGN_DESC_MAX_LENGTH)]
        public string Description { get; set; }

        public ItemDate Dates { get; set; }

        public string DropboxUrl { get; set; } // Added this line
    }

// SedaContext.cs:

public class SedaContext : DbContext
    {
        public DbSet<Company> Companies { get; set; }

        public DbSet<Design> Designs { get; set; }
…
}


// Global.aspx
protected void Application_Start()
        {

            // Application initialize
            // https://stackoverflow.com/questions/3600175/the-model-backing-the-database-context-has-changed-since-the-database-was-crea

            Database.SetInitializer<SedaContext>(null);

在包管理器控制台中,当我运行时 PM&GT;更新数据库,它抱怨数据库中已经有一个名为“公司”的对象。 “公司”是目前存在于我正在尝试更新的现有数据库中的表。

PM> update-database -verbose
Using StartUp project 'UI'.
Using NuGet project 'UI'.
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
Target database is: 'SedaDev' (DataSource: ., Provider: System.Data.SqlClient, Origin: Configuration).
No pending explicit migrations.
Applying automatic migration: 201405311730564_AutomaticMigration.
CREATE TABLE [dbo].[Companies] (
    [Id] [uniqueidentifier] NOT NULL DEFAULT newsequentialid(),
    [Name] [nvarchar](max),
    [Description] [nvarchar](max),
    [Owner_UserId] [int],
    CONSTRAINT [PK_dbo.Companies] PRIMARY KEY ([Id])
)
System.Data.SqlClient.SqlException (0x80131904): There is already an object named 'Companies' in the database.
...
   at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
   at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration)
   at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.Run()
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Update(String targetMigration, Boolean force)
   at System.Data.Entity.Migrations.UpdateDatabaseCommand.<>c__DisplayClass2.<.ctor>b__0()
   at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)
ClientConnectionId:fa9e9e62-aba0-435f-9309-e9fc8fbe19d5

There is already an object named 'Companies' in the database.

尝试1:搜索此错误后,我遇到了此解决方法: http://christesene.com/entity-framework-4-3-code-first-with-automatic-migrations/

建议我先跑

PM> Add-migration initial

Scaffolding migration 'initial'.
The Designer Code for this migration file includes a snapshot of your current Code First model. This snapshot is used to calculate the changes to your model when you scaffold the next migration. If you make additional changes to your model that you want to include in this migration, then you can re-scaffold it by running 'Add-Migration initial' again.

并删除了Up / Down方法:

即。我可以看到DropboxUrl是Up方法中的一个字段,但是我按照建议将其删除了。

public override void Up()
        {
/*
    CreateTable(
                "dbo.Companies",
                c => new
                    {
                        Id = c.Guid(nullable: false, identity: true),
                        Name = c.String(),
                        Description = c.String(),
                        Owner_UserId = c.Int(),
                    })
                .PrimaryKey(t => t.Id)
                .ForeignKey("dbo.UserProfiles", t => t.Owner_UserId)
                .Index(t => t.Owner_UserId);
...
  CreateTable(                "dbo.Designs",
                c => new
                    {
                        Id = c.Guid(nullable: false, identity: true),
                        Name = c.String(maxLength: 100),
                        Description = c.String(maxLength: 1000),
                        Dates_Create = c.DateTime(nullable: false),
                        Dates_LastUpdate = c.DateTime(nullable: false),
                        DropboxUrl = c.String(),
                        Project_Id = c.Guid(),
                    })
                .PrimaryKey(t => t.Id)
                .ForeignKey("dbo.Projects", t => t.Project_Id)
                .Index(t => t.Project_Id);
*/
        }

之后,我再次运行update-database,看起来是成功的。

PM> update-database -verbose
Using StartUp project 'UI'.
Using NuGet project 'UI'.
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
Target database is: 'SedaDev' (DataSource: phobos.spxis.com, Provider: System.Data.SqlClient, Origin: Configuration).
Applying explicit migrations: [201406020449030_initial].
Applying explicit migration: 201406020449030_initial.
INSERT [dbo].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])

VALUES (N'201406020449030_initial', N'Delecs.Seda.DataAccess.Migrations.Configuration',  0x1F8B0800000000000400ED1DCB72DCB8F19EAAFCC3D49C92544523D9F166
...
7B7C117028FAD9D8632C54E5F87C13A0D36590D83B7A73FA9F8AD368F7FFE3F0347EA807B340100 , N'6.0.2-21211')
Running Seed method

问题1:更新后我的表没有被更改(即代码中存在的DropboxUrl列未添加到数据库中)。

问题2:我也无法让数据库恢复到初始状态:

PM> update-database -TargetMigration $InitialDatabase
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
Reverting migrations: [201406020449030_initial].
Reverting automatic migration: 201406020449030_initial.
Automatic migration was not applied because it would result in data loss.
PM> update-database -TargetMigration $InitialDatabase -force
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
Reverting migrations: [201406020449030_initial].
Reverting automatic migration: 201406020449030_initial.
System.Data.SqlClient.SqlException (0x80131904): Could not drop object 'dbo.UserProfiles' because it is referenced by a FOREIGN KEY constraint.

尝试2:我在添加迁移时也尝试使用-IgnoreChanges标志: Automatic Migrations for ASP.NET SimpleMembershipProvider

PM> Add-migration initial -IgnoreChanges
Re-scaffolding migration 'initial'.

PM> update-database -verbose

同样,我看到同样的事情,更新数据库成功但数据库列DropboxUrl未添加到Designs表中。但是,如果我创建一个新数据库,则DropboxUrl列将按预期存在。

问题我怎样才能解决在执行update-database时数据库中出现了一个名为“Companies”的对象,并且仍然成功添加了我的列?它似乎应该是一个基本的方案,只是有效。

感谢。

1 个答案:

答案 0 :(得分:1)

当您在迁移中注释掉Up()和Down()方法时,您删除了添加数据库列的代码。

您应该按照以下内容更改Up()和Down():

public override void Up() {
   AddColumn("Companies", "DropboxUrl", x => x.String());
}

public override void Down() {
    DropColumn("Companies", "DropboxUrl");
}

要让Entity Framework将来为您解决此问题,您需要执行初始迁移,以便在将属性添加到代码之前了解现有表。例如Add-Migration -force -ignore.

然后添加列并转到Add-Migration AddedDropboxUrlColumn,它将生成Up()和Down()方法,如我在新迁移中所述。