C# 使用实体框架手动输入键

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

我试图首先将实体框架代码用于一个简单的数据库项目,但遇到了一个我根本无法解决的问题

我注意到EF为我的表设置的ID每次自动增加1,完全忽略了我为该字段手动输入的值。经过一些搜索,我认为禁用此行为的正确方法是:

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没有设置,但列仍然是自动生成的。以后是否有其他方法应用更改。因为在在我的情况下,我无法删除数据库。存在一些数据。我只是希望它在迁移运行时重新应用这些更改。因此,我将所有需要的内容都放在了模型创建中。但即使在运行迁移之后,它也无法工作。