EF Core迁移时触发NullReferenceException问题求助
解决EF Core OwnsMany嵌套OwnsOne导致的NullReferenceException
问题原因
这个空引用异常是EF Core处理**嵌套Owned Entity(OwnsMany内部嵌套OwnsOne)**时,隐式外键生成逻辑冲突引发的。当在OwnsMany配置块中嵌套OwnsOne时,EF Core无法正确识别父、子Owned Entity的关联关系,进而触发空引用错误。
修复方案
1. 显式配置Owned Entity间的关联外键
在嵌套的OwnsOne配置中,明确指定与父Owned Entity的外键关联,帮助EF Core正确识别依赖关系:
ftb.OwnsOne(ft => ft.BoardingPass, bp => { bp.ToTable("PassengerBoardingPasses"); bp.Property(b => b.Id) .ValueGeneratedNever() .HasConversion( b => b.Value, value => BoardingPassId.Create(value)); bp.Property(b => b.Gate) .HasMaxLength(8); bp.Property(b => b.BoardingTime) .IsRequired(); // 显式配置与父PassengerFlightTickets的外键关联 bp.WithOwner().HasForeignKey("FlightTicketId"); });
2. 调整导航属性访问模式的设置方式
将导航属性的访问模式设置与OwnsMany配置链式调用,避免在导航属性未完全初始化时访问:
builder.OwnsMany( p => p.FlightTicketIds, ftb => { // ... 原有OwnsMany内部配置 }) // 链式设置访问模式 .Metadata.SetPropertyAccessMode(PropertyAccessMode.Field);
3. 升级EF Core到稳定版本
若使用的是EF Core 5.x及更早版本,这类嵌套Owned Entity的bug已在后续版本中修复,建议升级到6.0或7.0的稳定版本后再尝试生成迁移。
4. 检查Owned Entity定义
确保FlightTicketIds对应的实体类(如PassengerFlightTicket)定义正确,所有属性有合适的访问修饰符,且无与EF Core映射逻辑冲突的自定义构造函数或属性逻辑。
修改后的完整配置代码
namespace Ceyehat.Infrastructure.Persistence.Configurations; public class PassengerConfigurations : IEntityTypeConfiguration<Passenger> { public void Configure(EntityTypeBuilder<Passenger> builder) { ConfigurePassengersTable(builder); ConfigurePassengerFlightTicketsTable(builder); } private void ConfigurePassengerFlightTicketsTable(EntityTypeBuilder<Passenger> builder) { builder.OwnsMany( p => p.FlightTicketIds, ftb => { ftb.ToTable("PassengerFlightTickets"); ftb.HasKey(ft => ft.Id); ftb.Property(ft => ft.Id) .ValueGeneratedNever() .HasConversion( ft => ft.Value, value => FlightTicketId.Create(value)); ftb.Property(ft => ft.FlightId) .ValueGeneratedNever() .HasConversion( ft => ft.Value, value => FlightId.Create(value)); ftb.Property(ft => ft.SeatId) .ValueGeneratedNever() .HasConversion( ft => ft.Value, value => SeatId.Create(value)); ftb.OwnsOne(ft => ft.BoardingPass, bp => { bp.ToTable("PassengerBoardingPasses"); bp.Property(b => b.Id) .ValueGeneratedNever() .HasConversion( b => b.Value, value => BoardingPassId.Create(value)); bp.Property(b => b.Gate) .HasMaxLength(8); bp.Property(b => b.BoardingTime) .IsRequired(); // 显式配置外键关联 bp.WithOwner().HasForeignKey("FlightTicketId"); }); }) .Metadata.SetPropertyAccessMode(PropertyAccessMode.Field); } private void ConfigurePassengersTable(EntityTypeBuilder<Passenger> builder) { builder.ToTable("Passengers"); builder.HasKey(p => p.Id); builder.Property(p => p.Id) .ValueGeneratedNever() .HasConversion( p => p.Value, value => PassengerId.Create(value)); builder.Property(p => p.CustomerId) .ValueGeneratedNever() .HasConversion( p => p.Value, value => CustomerId.Create(value)); } }
内容的提问来源于stack exchange,提问作者ad3m VALORANT
相关产品推荐
相关产品推荐

