【问题标题】:EF Core Exception: The property does not have a value set and no value generator is available for properties of typeEF Core 异常:该属性没有设置值,并且没有可用于类型属性的值生成器
【发布时间】: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”,这会混淆更改检测代码。

标签: c# entity-framework entity-framework-core


【解决方案1】:

这个异常是因为值转换器收到了一个空值。通过确保强类型 id 不为 null 并将以下行添加到属性配置中,我设法获得使用强类型 id 的自动递增整数: .Metadata.SetBeforeSaveBehavior(PropertySaveBehavior.Ignore)

编辑: 这种方法有一个陷阱。

这与更改跟踪有关。从 ef core 3.0 和 this GitHub issue 开始,当您对键使用自动递增且键值不是默认值时,实体将以“已修改”状态而不是“已添加”状态添加。这是当前解决方案的一个问题,因为我们从未为强类型 ID 设置 null。我们必须手动开始跟踪处于“已添加”状态的实体(使用 DbContext Add 方法),其他类型的自动跟踪将不起作用(例如,将实体添加到导航属性集合中以实现一对多关系)。正在通过this GitHub issue 跟踪对此的官方支持。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-20
    • 2022-12-15
    • 2015-12-09
    • 2021-08-24
    • 2021-10-22
    • 2013-09-15
    • 1970-01-01
    • 2020-12-04
    相关资源
    最近更新 更多