EF Core 8 CosmosDb 在获取具有 ValueObjects 列表的实体时“可为 Null 的对象必须有一个值”

问题描述 投票:0回答:1

我一直在将项目的基础设施从 CosmosClient 迁移到 Ef Core 8,并且在获取包含 ValueObjects 列表的实体时遇到异常“System.InvalidOperationException:Nullable 对象必须有值”

我的实体:

public sealed class Test : BaseEntity
{
    public string ShortName { get; set; } = null!;
    public string Name { get; set; } = null!;
    public List<Marker> Markers { get; set; } = [];

    public Test(string name, string? shortName = null)
    {
        Name = name;
        ShortName = shortName ?? name;
        Id = ShortName.EncodePolishLetterAndWhiteChars();
    }

    public Test() { }
}

标记:

public sealed class Marker : BaseEntity
{
    public Marker() { }
    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; set; } = null!;
    public string Name { get; set; } = null!;
    public decimal? LowerNorm { get; set; }
    public decimal? UpperNorm { get; set; }
    public string? Unit { get; set; }
}

DbContext OnModelCreating:

...
 modelBuilder
            .Entity<Test>()
            .ToContainer("Tests")
            .HasNoDiscriminator()
            .HasPartitionKey(r => r.ShortName);
        modelBuilder.Entity<Test>()
            .Property(r => r.Id)
            .ToJsonProperty("id");
        modelBuilder.Entity<Test>()
            .ComplexProperty(r => r.Markers)
            .IsRequired();
...

我尝试过使每个属性都可以为空,使列表可以为空,并使标记列表可以为空。当我不将标记设置为复杂属性时,我得到测试,但列表为空。

asp.net entity-framework entity-framework-core azure-cosmosdb
1个回答
0
投票

System.InvalidOperationException:可为 Null 的对象必须有一个值

当尝试使用可空对象的方法或属性而不首先检查其值时,会发生上述错误。该代码使用

ComplexProperty
方法,它用于配置非集合属性,而不是集合。如果 EF Core 将
Markers
集合解释为可为 null,并尝试在没有正确初始化或检查 null 的情况下访问其属性,则会导致错误。

尝试使用下面的代码,它使用

OwnsMany
方法来配置
Markers
实体对
Test
实体集合的所有权。它配置 EF Core 来处理测试实体与其标记值对象集合之间的关系。这可以防止在从 Cosmos DB 正确存储和检索数据期间发生
Nullable object must have a value
错误,如下面的输出所示。

public class AppDbContext : DbContext
{
    public DbSet<Test> Tests { get; set; } = null!;

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseCosmos(
            "<EndPointUri>",
            "<PrimaryKey>",
            databaseName: "firstDb"
        );
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Test>()
            .ToContainer("firstCont")
            .HasNoDiscriminator()
            .HasPartitionKey(r => r.ShortName);
        modelBuilder.Entity<Test>()
            .Property(r => r.Id)
            .ToJsonProperty("id");
        modelBuilder.Entity<Test>()
            .OwnsMany(r => r.Markers);
    }
}

class Program
{
    static void Main(string[] args)
    {
        using var context = new AppDbContext();

        // Sample data insertion
        var test1 = new Test("Test Entity 1", "Test1")
        {
            Markers = new List<Marker>
            {
                new Marker("Marker One", 10, 20, "kg", "Marker1"),
                new Marker("Marker Two", 5, 15, "m", "Marker2")
            }
        };

        var test2 = new Test("Test Entity 2", "Test2")
        {
            Markers = new List<Marker>
            {
                new Marker("Marker Three", 8, 18, "lbs", "Marker3")
            }
        };

        context.Tests.Add(test1);
        context.Tests.Add(test2);

        try
        {
            context.SaveChanges();
            Console.WriteLine("Data inserted successfully.");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"An error occurred while saving data: {ex.Message}");
        }
    }
}

输出:

Data inserted successfully.
© www.soinside.com 2019 - 2024. All rights reserved.