我通过实体框架代码创建了一个表,首先将主键设置为自动递增,但现在我想从列中删除该自动递增。我已尝试使用流畅的API:
public class ProductTypeMap: EntityTypeConfiguration<ProductType>
{
public ProductTypeMap()
{
// This is an enum effectively, so we need fixed IDs
Property(x => x.ProductTypeId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
}
}
和注释:
public class ProductType
{
[Required, Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ProductTypeId { get; set; }
public string ProductTypeName { get; set; }
}
在这两种情况下,他们都会生成相同的迁移代码:
public partial class removeproducttypeidentity : DbMigration
{
public override void Up()
{
DropPrimaryKey("dbo.ProductTypes");
AlterColumn("dbo.ProductTypes", "ProductTypeId", c => c.Int(nullable: false));
AddPrimaryKey("dbo.ProductTypes", "ProductTypeId");
}
public override void Down()
{
DropPrimaryKey("dbo.ProductTypes");
AlterColumn("dbo.ProductTypes", "ProductTypeId", c => c.Int(nullable: false, identity: true));
AddPrimaryKey("dbo.ProductTypes", "ProductTypeId");
}
}
但是,当我在数据库上运行迁移时,身份规范不会从SQL Server 2008数据库表中删除吗?
我还尝试在迁移过程中明确关闭Identity,如下所示,但是也没有这样做:
AlterColumn("dbo.ProductTypes", "ProductTypeId", c => c.Int(nullable: false, identity: false));
是否有另一种方法告诉SQL删除标识?
答案 0 :(得分:1)
您无法使用ALTER COLUMN
来设置列是否为标识列(How to alter column to identity(1,1))。
相反,你必须:
CREATE
TMP_table包含原始列的列,但ID列设置为identity:false SET IDENTITY_INSERT [TMP_Table] ON
SET IDENTITY_INSERT [TMP_Table] OFF
DROP
原始表EXECUTE sp_rename
)提示:更改SQL Management Studio中的列并检查发出的脚本(SQL SERVER – Add or Remove Identity Property on Column)。
答案 1 :(得分:1)
如果要从主键中删除标识,则需要删除并重新创建表及任何关联的外键。
只能通过重新创建表来从列中删除标识规范。查看ALTER TABLE - ALTER COLUMN
语句:没有语法可以更改(添加或删除)标识规范。
参考流动网站:
Cant remove identity attribute from PK
Entering keys manually with Entity Framework
EF6: Switching Identity On/Off with a Custom Migration Operation
Remove Identity from Primary Key with Drop and Recreate Table
答案 2 :(得分:0)
由于这两个答案解释了从列中删除标识所涉及的内容,我想出了一个新版本的迁移,它实现了从PK列中删除标识。
此解决方案会丢失表格中的所有数据。这在我的情况下是可以接受的,因为所讨论的表是一个表示枚举的表,因此由我的种子方法手动填充(我首先删除了身份,因此我可以指定用于PK Id字段的值)。 请勿对用户输入的数据使用此方法!
public partial class removeproducttypeidentity : DbMigration
{
public override void Up()
{
DropForeignKey("dbo.Products", "ProductTypeId", "dbo.ProductTypes");
DropPrimaryKey("dbo.ProductTypes");
DropTable("dbo.ProductTypes");
CreateTable(
"dbo.ProductTypes",
c => new
{
ProductTypeId = c.Int(nullable: false),
ProductTypeName = c.String(),
})
.PrimaryKey(t => t.ProductTypeId);
AddForeignKey("dbo.Products", "ProductTypeId", "dbo.ProductTypes", "ProductTypeId");
}
public override void Down()
{
DropForeignKey("dbo.Products", "ProductTypeId", "dbo.ProductTypes");
DropPrimaryKey("dbo.ProductTypes");
DropTable("dbo.ProductTypes");
CreateTable(
"dbo.ProductTypes",
c => new
{
ProductTypeId = c.Int(nullable: false, identity: true),
ProductTypeName = c.String(),
})
.PrimaryKey(t => t.ProductTypeId);
AddForeignKey("dbo.Products", "ProductTypeId", "dbo.ProductTypes", "ProductTypeId");
}
}
答案 3 :(得分:0)
正如其他人所说,EF不能本地执行此操作,尽管它会创建一个使其看起来像它的迁移脚本。我已经尝试了很多方法,我发现最简单的方法是:
add-migration [your migration name]
)Up
方法中的代码
Sql (@" ");
然后应该为您提供删除身份的迁移,并且可以成功地在数据库的其他副本上运行。
注意:生成的Down
方法无效,因为它将重新添加身份which EF also can't do。如果您需要Down
方法来创建您添加的SQL的副本并进行调整以再次创建具有该标识的表。
上述方法可以快速了解@Georg Patscheider在答案中所描述的内容。
答案 4 :(得分:0)
此解决方案适用于以下情况:
示例实体:
public class Foo
{
[Key]
public int Id { get; set; }
}
public class Bar
{
// This is the foreign key:
public int FooId { get; set; }
public virtual Foo Foo { get; set; }
}
将 Foo
更改为:
public class Foo
{
[Key]
public int Id { get; set; }
[Index(IsUnique = true)]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int NewId { get; set; }
}
生成迁移:
public partial class AddNewId : DbMigration
{
public override void Up()
{
AddColumn("dbo.Foos", "NewId", c => c.Int(nullable: false));
// This is a custom line which copies the data from the old column to the new.
Sql("UPDATE dbo.Foos SET NewId = Id");
CreateIndex("dbo.Foos", "NewId", unique: true);
}
public override void Down()
{
DropIndex("dbo.Foos", new[] { "NewId" });
DropColumn("dbo.Foos", "NewId");
}
}
Foo.Id
更改为 Foo.NewId
这是棘手的部分。
对 Foo
实体的任何引用仍在使用旧的 Id
属性而不是新的 NewId
属性。
使用 Visual Studio:
Foo.Id
属性Foo.NumericId
的名称更改为 Foo.Id
(不更新引用)Foo.Id
重命名回 Foo.NumericId
但让 VS 也更改所有引用Foo.Id
属性中重新注释Foo.NewId
设为主键public class Foo
{
public int Id { get; set; }
[Key]
[Index(IsUnique = true)]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int NewId { get; set; }
}
Bar.FooId
所有实体现在都需要引用 Foo.NewId
而不是 Foo.Id
。
更改Bar
:
public class Bar
{
// This is the foreign key:
public int FoodNewId { get; set; }
public virtual Foo Foo { get; set; }
}
创建一个新的迁移:
public partial class AddNewIdPart2 : DbMigration
{
public override void Up()
{
DropForeignKey("dbo.Bars", "FooId", "dbo.Foos");
RenameColumn(table: "dbo.Bars", name: "FooId", newName: "FooNewId");
DropPrimaryKey("dbo.Foos");
AddPrimaryKey("dbo.Foos", "NewId");
AddForeignKey("dbo.Bars", "FooNewId", "dbo.Foos", "Newid");
}
public override void Down()
{
// ...
}
}
这应该就是一切。
如果需要,您现在可以删除旧的 Foo.Id
列。