我一直在将项目的基础设施从 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();
...
我尝试过使每个属性都可以为空,使列表可以为空,并使标记列表可以为空。当我不将标记设置为复杂属性时,我得到测试,但列表为空。
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.