You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core 8 CosmosDB查询含值对象列表实体时遇Nullable异常

解决EF Core 8 Cosmos查询值对象列表时的Nullable异常问题

问题根源分析

你遇到的System.InvalidOperationException: Nullable object must have a value异常,核心原因有两个:

  • Marker类继承了带标识属性(如Id)的BaseEntity,但你将其作为值对象集合通过ComplexProperty映射,EF Core Cosmos会尝试绑定标识属性,但数据库中该字段不存在或为null,导致非空断言失败。
  • 实体类中Marker的ShortName和Name被标记为非空(null!),但如果数据库中对应的Markers元素存在null值,EF Core映射时会强制赋值null给非空属性,触发异常。

解决方案

1. 将Marker修正为纯值对象(推荐)

值对象不需要身份标识(Id),因此移除对BaseEntity的继承,并确保属性可空性与数据匹配:

public sealed class Marker // 移除BaseEntity继承
{
    public Marker(string name,
        decimal? lowerNorm = null,
        decimal? upperNorm = null,
        string? unit = null,
        string? shortName = null)
    {
        ShortName = shortName ?? name;
        Name = name;
        LowerNorm = lowerNorm;
        UpperNorm = upperNorm;
        Unit = unit;
    }

    public string ShortName { get; private set; } = null!;
    public string Name { get; private set; } = null!;
    public decimal? LowerNorm { get; private set; }
    public decimal? UpperNorm { get; private set; }
    public string? Unit { get; private set; }

    // 值对象相等性实现(可选规范)
    public override bool Equals(object? obj)
    {
        if (obj is not Marker other) return false;
        return ShortName == other.ShortName && Name == other.Name && LowerNorm == other.LowerNorm && UpperNorm == other.UpperNorm && Unit == other.Unit;
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(ShortName, Name, LowerNorm, UpperNorm, Unit);
    }
}

2. 调整EF Core映射配置

针对值对象集合,确保ComplexProperty配置正确,同时禁用不必要的标识映射:

modelBuilder.Entity<Test>(entity =>
{
    entity.ToContainer("Tests")
          .HasNoDiscriminator()
          .HasPartitionKey(r => r.ShortName);
    entity.Property(r => r.Id).ToJsonProperty("id");
    
    // 配置Markers为复杂类型集合,显式指定属性映射
    entity.ComplexProperty(r => r.Markers, cp =>
    {
        cp.IsRequired();
        cp.Property(m => m.ShortName).ToJsonProperty("shortName").IsRequired();
        cp.Property(m => m.Name).ToJsonProperty("name").IsRequired();
        cp.Property(m => m.LowerNorm).ToJsonProperty("lowerNorm");
        cp.Property(m => m.UpperNorm).ToJsonProperty("upperNorm");
        cp.Property(m => m.Unit).ToJsonProperty("unit");
    });
});

3. 修复数据库中现有数据的不一致性

检查Cosmos容器中Tests文档的Markers数组,确保:

  • 每个Marker元素的shortName和name字段不为null(对应实体类的非空属性)
  • 不存在null的Marker元素

4. 临时调试规避方案(不推荐)

如果暂时无法修改实体或数据,可将Marker的非空属性改为可空,保留null!断言作为临时措施:

public string? ShortName { get; set; } = null!;
public string? Name { get; set; } = null!;

验证步骤

  1. 重新生成迁移并更新Cosmos容器(若使用迁移)
  2. 执行查询操作,确认异常消失,Markers列表能正确加载

内容的提问来源于stack exchange,提问作者kamildobkowski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 20:00:17