C# 使用实体框架手动输入键
我试图首先将实体框架代码用于一个简单的数据库项目,但遇到了一个我根本无法解决的问题 我注意到EF为我的表设置的ID每次自动增加1,完全忽略了我为该字段手动输入的值。经过一些搜索,我认为禁用此行为的正确方法是:C# 使用实体框架手动输入键,c#,sql,asp.net,entity-framework,entity-framework-core,C#,Sql,Asp.net,Entity Framework,Entity Framework Core,我试图首先将实体框架代码用于一个简单的数据库项目,但遇到了一个我根本无法解决的问题 我注意到EF为我的表设置的ID每次自动增加1,完全忽略了我为该字段手动输入的值。经过一些搜索,我认为禁用此行为的正确方法是: modelBuilder.Entity<Event>().Property(e => e.EventID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); modelBuilder.Entity().P
modelBuilder.Entity<Event>().Property(e => e.EventID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
modelBuilder.Entity().Property(e=>e.EventID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
然而,现在我只是得到了这个错误,我不知道为什么:
未处理的异常:
System.Data.Entity.Infrastructure.DbUpdateException:错误
更新条目时发生。有关详细信息,请参见内部异常
细节---
System.Data.UpdateException:更新条目时出错。有关详细信息,请参见内部异常。-->
System.Data.SqlClient.SqlException:无法为插入显式值
当identity_INSERT设置为OFF时,表“事件”中的identity列
如果有帮助的话,下面是讨论中的POCO类:
public class Event
{
[Key, Required]
public int EventID { get; set; }
public string EventType { get; set; } //TODO: Event Type Table later on
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public virtual ICollection<Match> Matches { get; set; }
public virtual ICollection<EventParticipation> EventParticipation { get; set; }
}
公共类事件
{
[钥匙,必填]
public int EventID{get;set;}
公共字符串EventType{get;set;}//TODO:稍后的事件类型表
公共日期时间起始日期{get;set;}
公共日期时间结束日期{get;set;}
公共虚拟ICollection匹配{get;set;}
公共虚拟ICollection事件参与{get;set;}
}
提前感谢。默认情况下,实体框架假定数据库生成一个整数主键(相当于添加属性
HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
或调用属性(e=>e.EventID)。HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
在Fluent API中
如果查看创建表的迁移,您应该会看到:
CreateTable(
"dbo.Events",
c => new
{
EventID = c.Int(nullable: false, identity: true),
//etc
})
.PrimaryKey(t => t.EventID );
然后,您使用Fluent API将模型更改为DatabaseGenerated。无。EF将其放入迁移中:
AlterColumn("dbo.Events", "EventID", c => c.Int(nullable: false, identity: false))
生成的sql如下所示:
ALTER TABLE[dbo].[Events]ALTER COLUMN[EventID][int]不为NULL
实际上,它确实是蹲式的。从一个列开始并不是一件小事。您需要删除并重新创建表或创建一个新列,然后您必须复制数据并修复外键。因此,EF不为您这样做也就不足为奇了
您需要确定如何最好地为自己完成迁移。您可以将迁移回滚到0,并在指定了DatabaseGeneratedOption之后重新构建支架。无,或者您可以手动更改迁移以删除并重新创建表
也可以删除并重新创建列:
DropColumn("Customer", "CustomerId");
AddColumn("Customer", "CustomerId", c => c.Long(nullable: false, identity: false));
编辑
或者您也可以因为我更喜欢属性,为了完整起见,这里是另一种选择:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
注意:这也适用于EF Core。注意:如果您发现属性本身使维护模型更容易,也可以直接在属性本身上使用属性。[DatabaseGeneratedAttribute(DatabaseGeneratedOption.None)]
谢谢。我最终通过删除整个数据库并让EF从头开始创建来修复它。现在我知道为什么会发生这种情况,将来我只需要删除表。我设置了DatabaseGenerated。从一开始就使用Fluent API没有设置,但列仍然是自动生成的。以后是否有其他方法应用更改。因为在在我的情况下,我无法删除数据库。存在一些数据。我只是希望它在迁移运行时重新应用这些更改。因此,我将所有需要的内容都放在了模型创建中。但即使在运行迁移之后,它也无法工作。