我正在使用代码首次迁移现有数据库。我使用逆向工程功能来生成所有初始实体。但是,数据库设计得不好,其中一个表没有指定主键。显然,实体框架尽力推断出主键,并没有做到正确。看起来它决定将两个字段作为复合主键。
我想删除其中一个错误认为属于主键的字段,并导致错误。
以下是为其创建实体时表的原始架构:
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_ID
和Field_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实际指定为主键。
有什么想法吗?
答案 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");
}