为啥 EF Core 5 不使用我的实体“地址”的“Id”属性上的“[Key]”属性创建“主键自动增量”?

Posted

技术标签:

【中文标题】为啥 EF Core 5 不使用我的实体“地址”的“Id”属性上的“[Key]”属性创建“主键自动增量”?【英文标题】:Why EF Core 5 does not create "Primary Key Autoincrement" using "[Key]" attribute on "Id" property of my entity "Address"?为什么 EF Core 5 不使用我的实体“地址”的“Id”属性上的“[Key]”属性创建“主键自动增量”? 【发布时间】:2021-02-21 06:19:27 【问题描述】:

我在我的 VS 2019 项目中使用 Microsoft.EntityFrameworkCore v5.0.3(在 .NET Core 3.1 上运行)。

正如您在实体类Address 中看到的,第一个属性int Id 具有属性[Key]

[Index(nameof(Country))]
[Index(nameof(ZIP))]
[Index(nameof(City))]
public class Address

    [Key]
    public int Id  get; set; 

    [Timestamp]
    public byte[] RowVersion  get; set; 

    public DateTime CreatedAt  get; set;  = DateTime.UtcNow;
    public DateTime ChangedAt  get; set;  = DateTime.UtcNow;

    [StringLength(EFConst.MAX_LEN_COUNTRY)]
    public string Country  get; set;      
    
    [StringLength(EFConst.MAX_LEN_ZIP)]
    public string ZIP  get; set; 
    
    [StringLength(EFConst.MAX_LEN_CITY)]
    public string City  get; set; 

    [StringLength(EFConst.MAX_LEN_STREET)]
    public string Street  get; set; 

但在创建数据库架构后,我在使用 Microsoft SQL Server Management Studio 的 CREATE TABLE 脚本中既看不到 PRIMARY KEY 也看不到 AUTOINCREMENT,如您在此处看到的:

CREATE TABLE [dbo].[Addresses]
(
    [ID] [int] NOT NULL,
    [RowVersion] [timestamp] NOT NULL,
    [CreatedAt] [datetime] NOT NULL,
    [ChangedAt] [datetime] NOT NULL,
    [Country] [nvarchar](64) NULL,
    [ZIP] [nvarchar](32) NULL,
    [City] [nvarchar](64) NULL,
    [Street] [nvarchar](128) NULL,

    CONSTRAINT [PK_dbo.Addresses] 
        PRIMARY KEY CLUSTERED ([ID] ASC)
                WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                      IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                      ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

现在,当这段代码被执行时:

var addr1 = db.Addresses.Add(new Address

    Country = "SampleCountry",
    City = "SampleCity",
    ZIP = "12345",
    Street = "SampleStreet 123"
);

db.SaveChanges();

我在db.SaveChanges() 收到此异常:

Microsoft.EntityFrameworkCore.DbUpdateException:更新条目时出错。详情见内部异常

内部异常

SqlException:无法将值 NULL 插入列“ID”、表“NSA.dbo.Addresses”;列不允许空值。插入失败。声明已终止。

我不知道为什么会抛出异常。

为什么表Addresses中的列ID没有定义为PRIMARY AUTOINCREMENT

我已经搜索/谷歌了整个互联网......并到达了它的边界。

solutions on ***(或其他地方)都不适合我! 正如official documentation of EF Core 中所述,我的简单项目应该可以工作!

我已经在以下实验(单个和一些组合)进行了逐步尝试和错误,但没有成功:

使用“数据注释”(属性): [Key] [Required] [Required, DatabaseGenerated(DatabaseGeneratedOption.Identity)] [DatabaseGenerated(DatabaseGeneratedOption.Identity)]Id 重命名为AddressId(+ 以上使用属性的组合) 通过覆盖 void OnModelCreating(...) 和使用 modelBuilder.Entity<Address>().HasKey(a => a.Id); 来使用 Fluent API 将属性 Id 重新定义为:int? Idint IDint? IDint AddressIdint? AddressIdint AddressIDint? AddressID

我做错了吗?

如何使用 EF Core 将“Address”类的“Id”属性定义为 PRIMARY KEY + AUTOINCREMENT?

谢谢!

【问题讨论】:

您在后端使用什么数据库?例如 SQL Server 没有有一个 AUTOINCREMENT 关键字 - 它被称为 IDENTITY @marc_s 我正在使用 SQL EXPRESS (MSSQL 15)。 SQL创建脚本中也没有“IDENTITY”关键字! 您在使用此注释后是否进行了另一次迁移和数据库更新? [DatabaseGenerated(DatabaseGeneratedOption.Identity)] @MohamedAdel 你是对的!问题是我在重新创建数据库之前没有删除它(facepalm)。非常感谢您的帮助并挽救了我的一天。 @user14867525 不客气,我已添加为答案,请接受以供进一步需求 【参考方案1】:

您在使用此注解后是否进行了另一次迁移和数据库更新?

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]

您只需要进行另一次迁移并更新您的数据库

【讨论】:

这应该没有必要。文档说:“按照惯例,名为 Id 或 Id 的属性将被配置为实体的主键。”【参考方案2】:

感谢@MohamedAdel,我解决了删除数据库并重新创建它的问题。现在“ID”列定义为

[Id] [int] IDENTITY(1,1) NOT NULL

一切都很好。 谢谢大家的帮助!

【讨论】:

以上是关于为啥 EF Core 5 不使用我的实体“地址”的“Id”属性上的“[Key]”属性创建“主键自动增量”?的主要内容,如果未能解决你的问题,请参考以下文章

EF Core 5.0 - 更新 ASP.NET Core Web API 中的多对多实体

如何将同一列添加到 EF Core 中的所有实体?

正确配置多对一关系 ef core

EF Core - 为啥“无限”嵌套急切加载?

EF Core - 为啥显式加载非常慢?

VS2019 使用EF Core Power Tools 生成Sqlserver的数据库实体类