Domain driven design EF Core DDD多对一关系,外键始终为空

Domain driven design EF Core DDD多对一关系,外键始终为空,domain-driven-design,many-to-one,ef-core-5.0,Domain Driven Design,Many To One,Ef Core 5.0,关系:许多产品可以属于同一类别。简化了域模型以关注该问题 我使用的是EFCoreV5.0 产品型号类别: 公共类产品:实体,IAggregateRoot { 受保护产品(){} 公共产品(字符串名称、类别):this() { 名称=名称; 类别=类别; } 公共字符串名称{get;} 公共虚拟类别{get;} } 类别车型类别: 公共类类别:实体 { 受保护类别(){} 公共类别(字符串名称):this() { 名称=名称; } 公共字符串名称{get;} } 产品配置: 公共类产品配置:I

关系:许多产品可以属于同一类别。简化了域模型以关注该问题

我使用的是EFCoreV5.0

产品
型号类别:

公共类产品:实体,IAggregateRoot
{
受保护产品(){}
公共产品(字符串名称、类别):this()
{
名称=名称;
类别=类别;
}
公共字符串名称{get;}
公共虚拟类别{get;}
}
类别
车型类别:

公共类类别:实体
{
受保护类别(){}
公共类别(字符串名称):this()
{
名称=名称;
}
公共字符串名称{get;}
}
产品配置:

公共类产品配置:IEntityTypeConfiguration
{
公共void配置(EntityTypeBuilder)
{
建造商。可转让(“产品”);
HasKey(x=>x.Id);
builder.Property(x=>x.Id)
.HasValueGenerator()
.ValueGeneratedOnAdd();
builder.Property(x=>x.Name).IsRequired().HasMaxLength(500);
builder.HasOne().WithMany();
}
#端区
}
类别配置:

公共类类别配置:IEntityTypeConfiguration
{
公共void配置(EntityTypeBuilder)
{
建造商。可转让(“类别”);
HasKey(x=>x.Id);
builder.Property(x=>x.Id)
.HasValueGenerator()
.ValueGeneratedOnAdd();
builder.Property(x=>x.Name)
.IsRequired()
.HasMaxLength(255);
}
#端区
}
因此,在准备好此配置和域模型后,当尝试插入一些种子数据时,
CategoryId
属性(EF Core创建的阴影属性,而不是域模型中的阴影属性)始终为空

公共类ProductDbContextSeeder
{
公共异步任务SeedAsync(ProductDbContext上下文)
{
var category=wait context.Categories.FirstOrDefaultAsync(x=>x.Name==“测试类别”);
如果(类别为空)
{
类别=新类别(“测试类别”);
wait context.Categories.AddAsync(category);
wait context.saveChangesSync();
}
var product=wait context.Products.FirstOrDefaultAsync(x=>x.Name==“测试产品”);
如果(产品为空)
{
产品=新产品(“测试产品”,类别);
context.Products.Attach(产品);
wait context.saveChangesSync();
}
}
}
在调用
context.saveChangesSync()
之前,我检查了条目的状态,似乎实体处于正确的状态,如下所示:

保存类别时:

  • 类别->已添加
保存产品时:

  • 产品->已添加
  • 类别->未更改
我错过了什么?感谢您的任何提示和指点


谢谢

在第一次
savechangesync
呼叫后,
category
保持不变,但这并不意味着没有建立产品类别关联。保存后,新产品将新类别的CategoryId设置为FK。顺便说一句,最后只需调用一个
savechangesync
就足够了。是的,你说得对,我只是单独测试了一下如何保存。原来是这样的。但是,在调用SaveChanges之后,CategryId不会填充到产品表中,我错过了getter-only属性。我认为引用导航属性不支持它们。它至少应该有一个私人setter。哦:/谢谢你发现了@GertArnold。就这样。在某些时候,我有只读属性,但有使用私有备份字段的配置。感谢您的帮助。实际上问题出在您的配置中-
builder.HasOne().WithMany(),这基本上是告诉EF忽略导航属性(只读或不只读)。当然它应该是HasOne(x=>x.Category)