如何修复Entity Framework生成的代码中的错误

时间:2014-07-04 02:50:58

标签: entity-framework ef-migrations

我正在使用代码首次迁移现有数据库。我使用逆向工程功能来生成所有初始实体。但是,数据库设计得不好,其中一个表没有指定主键。显然,实体框架尽力推断出主键,并没有做到正确。看起来它决定将两个字段作为复合主键。

我想删除其中一个错误认为属于主键的字段,并导致错误。

以下是为其创建实体时表的原始架构:

CREATE TABLE [dbo].[Table1](
    [The_ID] [bigint] IDENTITY(1,1) NOT NULL,
    [Field_1] [varbinary](max) NULL,
    [Field_2] [bigint] NULL,
    [Field_3] [varbinary](max) NULL,
    [Field_4] [datetime] NULL,
    [Field_5] [bit] NOT NULL
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[Table1] ADD  CONSTRAINT [DF_Table1_F5]  DEFAULT ((0)) FOR [Field_5]
GO

The_ID应该被指定为主键,但你可以看到它不是。这是Visual Studio生成的类:

public partial class Table1
{
    [Key]
    [Column(Order = 0)]
    public long The_ID { get; set; }

    public byte[] Field_1 { get; set; }

    public long? Field_2 { get; set; }

    public byte[] Field_3 { get; set; }

    public DateTime? Field_4 { get; set; }

    [Key]
    [Column(Order = 1)]
    public bool Field_5 { get; set; }
}

显然决定将The_IDField_5变成复合主键。至少我是如何解释这段代码的。现在,我实际上需要从表中删除Field_5。我创建了一个迁移来执行此操作,但由于实体框架认为它是主键的一部分,它会执行奇怪的操作,例如删除主键并重新添加它,这会导致错误。以下是生成的迁移代码:

public override void Up()
{
    DropPrimaryKey("dbo.Table1");
    AlterColumn("dbo.Table1", "The_ID", c => c.Long(nullable: false, identity: true));
    AddPrimaryKey("dbo.Table1", "The_ID");
    DropColumn("dbo.Table1", "Field_5");
}

运行此操作会导致以下错误:

  

ALTER TABLE [dbo]。[Table1] DROP CONSTRAINT [PK_dbo.Table1]   System.Data.SqlClient.SqlException(0x80131904):' PK_dbo.Table1'不是约束。

那么如何摆脱这种混乱?

我尝试从[Key]The_ID删除Field_5属性并使用

创建虚拟迁移
  

添加迁移虚拟-IgnoreChanges

认为我可以将[Key]属性添加回The_ID并删除Field_5,但它不会让我创建迁移,除非至少有一个字段是使用[Key]属性指定。但是,如果我这样做以实现虚拟迁移,那么我无法在实际迁移中执行此操作,因此我无法使用代码优先迁移将The_ID实际指定为主键。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

如果您有一个没有主键的表,则Database EntityFramework会将表中的每个不可为空的列解释为主键的一部分。

在这种情况下,您可以从生成的Migration中删除前两行,因为没有要删除的主键。 EntityFramework只是不知道这个事实。

public override void Up()
{
    //DropPrimaryKey("dbo.Table1");
    //AlterColumn("dbo.Table1", "The_ID", c => c.Long(nullable: false, identity: true));
    AddPrimaryKey("dbo.Table1", "The_ID");
    DropColumn("dbo.Table1", "Field_5");
}