ValueGenerateOnAdd 没有效果

use*_*794 8 c# entity-framework-core

例如,我有下一张表:

CREATE TABLE Person (
    id int IDENTITY(1,1) NOT NULL PK,
    firstName nvarchar(20) NOT NULL,
    lastName nvarchar(30) NOT NULL,
    birtdate datetimeoffset(7) NOT NULL,
    age int,
    height int,
)
Run Code Online (Sandbox Code Playgroud)

实体映射有一部分:

public void Configure(EntityTypeBuilder<Person> builder)
{
    ...
    builder.HasKey(k => k.Id);

    builder.Property(k => k.Id)
        .ValueGeneratedOnAdd()
        .IsRequired();
    ...
}
Run Code Online (Sandbox Code Playgroud)

我的 MS SQL 服务器在客户端具有该表,在服务器端具有相同的表。我的程序从客户端的表中检索数据并将其发送到服务器,在服务器上将数据添加到数据库中。检索数据期间没有问题,但当我尝试插入数据时出现错误:

SqlException: Cannot insert explicit value for identity column in table 'Person' when IDENTITY_INSERT is set to OFF.
Run Code Online (Sandbox Code Playgroud)

尽管.ValueGeneratedOnAdd()

当我检索数据时,我得到具有填充 Id 属性(1、2、3 等)的实体,但我认为这并不重要。

Iva*_*oev 10

当我检索数据时,我得到具有填充 Id 属性(1、2、3 等)的实体,但我认为这并不重要。

实际上它确实重要并且是问题的原因。ValueGenerated对于将值设置为类型的非默认值的属性(null对于可为空类型、0数字类型等)没有影响。

EF Core 文档的生成值部分对此行为进行了解释:

如果您将一个实体添加到具有分配给属性的值的上下文,则 EF 将尝试插入该值而不是生成新值。如果属性未分配 CLR 默认值(nullfor string0for intGuid.EmptyforGuid等),则认为该属性已分配值。有关详细信息,请参阅生成属性的显式值

这基本上是为了在上传数据时允许所谓的“身份插入”场景。有关详细信息,请参阅SQL Server IDENTITY 列中的显式值

话虽如此,如果您不希望出现这种行为,请确保在调用将实体添加到数据库上下文/集之前将所有实体Id(PK) 属性设置为。0


小智 5

我解决了添加UseSqlServerIdentityColumn()Id 属性的配置:

builder.Property(k => k.Id)
    .ValueGeneratedOnAdd()
    .UseSqlServerIdentityColumn()
    ...
Run Code Online (Sandbox Code Playgroud)

请注意,它是Microsoft.EntityFrameworkCore.SqlServerSqlServerPropertyBuilderExtensions包内部的一部分。

请注意,.UseSqlServerIdentityColumn()已弃用并更改为.UseIdentityColumn() “Microsoft.EntityFrameworkCore.SqlServer”版本 3.x 和(撰写本文时为 3.0 和 3.1)

  • 虽然 int/bigint 作为 PrimaryKey 表现更好,但使用 GUID(唯一标识符)允许构建完整的对象模型并执行基于集合的插入。如果客户端生成 guid,它会更容易,但代价是坏的 pk 碎片。如果数据库生成 guid (newsequentialids),它的性能会更好(pk 碎片更少),但更难拉取。#只是在说。无论如何,感谢您的回答! (4认同)