EF Core 异常:该属性没有设置值,并且没有可用于类型属性的值生成器
Posted
技术标签:
【中文标题】EF Core 异常:该属性没有设置值,并且没有可用于类型属性的值生成器【英文标题】:EF Core Exception: The property does not have a value set and no value generator is available for properties of type 【发布时间】:2022-01-15 06:10:48 【问题描述】:我正在使用 .net6 和 efcore6。
我有一个名为 Notification 的数据库实体,它的主键类型为 NotificationId。我正在使用类型转换器和值转换器来使 EFCore 能够在复杂类型和基本 CLR 类型之间进行转换。我的复杂类型基于整数。
当我尝试将新记录保存到此数据库时,我收到一个异常,似乎表明我没有配置值生成器。
完整的例外是: “Notification.Id”属性没有设置值,并且“NotificationId”类型的属性没有可用的值生成器。在添加实体之前为属性设置一个值,或者在“OnModelCreating”中为“NotificationId”类型的属性配置一个值生成器
在我的实体类型配置中,我有:
builder.Property(x => x.Id)
.ValueGeneratedOnAdd()
.HasConversion(
x => x.Value,
x => IntIdValue.From<TKey>(x))
;
builder.HasKey(x => x.Id);
这正确地将 Id 类型设置为 Identity,以及迁移中显示的主键:
migrationBuilder.CreateTable(
name: "Notification",
columns: table => new
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
...
constraints: table =>
table.PrimaryKey("PK_Notification", x => x.Id);
如何说服 EF 使用身份值生成器?
【问题讨论】:
值转换器不会为空值运行。这可能是问题吗? docs.microsoft.com/en-us/ef/core/modeling/… @DavidBrowne-Microsoft 这是一个有趣的想法,但我明白这就是 EF 知道如何处理数据库生成的值的方式。我尝试将“值”设置为 0,但由于多个记录具有相同的“idl”,这会混淆更改检测代码。 【参考方案1】:这个异常是因为值转换器收到了一个空值。通过确保强类型 id 不为 null 并将以下行添加到属性配置中,我设法获得使用强类型 id 的自动递增整数:
.Metadata.SetBeforeSaveBehavior(PropertySaveBehavior.Ignore)
编辑: 这种方法有一个陷阱。
这与更改跟踪有关。从 ef core 3.0 和 this GitHub issue 开始,当您对键使用自动递增且键值不是默认值时,实体将以“已修改”状态而不是“已添加”状态添加。这是当前解决方案的一个问题,因为我们从未为强类型 ID 设置 null。我们必须手动开始跟踪处于“已添加”状态的实体(使用 DbContext Add 方法),其他类型的自动跟踪将不起作用(例如,将实体添加到导航属性集合中以实现一对多关系)。正在通过this GitHub issue 跟踪对此的官方支持。
【讨论】:
以上是关于EF Core 异常:该属性没有设置值,并且没有可用于类型属性的值生成器的主要内容,如果未能解决你的问题,请参考以下文章
要在 EF Core 中添加没有外键的导航属性,使用 .NET Core Web API 进行 DB-first 迁移
什么是 Entity Framework Core 属性等价于 modelBuilder 的 HasDefaultValueSql?
非托管代码中的 ASP Net Core 1.1 和 EF 6 异常?