EF Core 7中鉴别器搭配子导航属性未填充问题求助
问题:EF Core中鉴别器关联的Denials列表无法填充
SQL数据库中Order与OrderDenial、OrderLine与OrderLineDenial之间无外键(FK)关联,实体类定义如下:
public partial class Order { public int OrderId { get; set; } public virtual ICollection<OrderLine> OrderLines { get; set; } public virtual ICollection<OrderDenial> Denials { get; set; } } public partial class OrderLine { public int OrderLineId { get; set; } public virtual ICollection<OrderLineDenial> Denials { get; set; } } public partial class Denial { public int DenialId { get; set; } public int ReferenceId { get; set; } public string ReferenceType { get; set; } } public partial class OrderDenial : Denial { } public partial class OrderLineDenial : Denial { }
上下文配置如下:
public class OrderContext : DbContext { public OrderContext(DbContextOptions<OrderContext> options) : base(options) { } protected OrderContext() { } public virtual DbSet<Order> Orders { get; set; } public virtual DbSet<OrderDenial> OrderDenials { get; set; } public virtual DbSet<OrderLine> Claims { get; set; } public virtual DbSet<OrderLineDenial> OrderLineDenials { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.ApplyConfiguration(new OrderConfiguration()); modelBuilder.ApplyConfiguration(new OrderLineConfiguration()); modelBuilder.ApplyConfiguration(new DenialConfiguration()); } public partial class OrderConfiguration : IEntityTypeConfiguration<Order> { public void Configure(EntityTypeBuilder<Order> entity) { entity.ToTable(nameof(Order)); entity.HasMany(e => e.Denials) .WithOne() .HasForeignKey(e => e.ReferenceId) .HasPrincipalKey(e => e.OrderId); } } public partial class OrderLineConfiguration : IEntityTypeConfiguration<OrderLine> { public void Configure(EntityTypeBuilder<OrderLine> entity) { entity.ToTable(nameof(OrderLine)); entity.HasMany(e => e.Denials) .WithOne() .HasForeignKey(e => e.ReferenceId) .HasPrincipalKey(e => e.OrderLineId); } } public partial class DenialConfiguration : IEntityTypeConfiguration<Denial> { public void Configure(EntityTypeBuilder<Denial> entity) { entity.ToTable(nameof(Denial)); entity.HasDiscriminator<string>(x => x.ReferenceType) .HasValue<OrderDenial>(nameof(Order)) .HasValue<OrderLineDenial>(nameof(OrderLine)); } } }
查询数据的LINQ语句:
var query = _orderContext.Orders .Include(x => x.Denials) .Include(x => x.OrderLines).ThenInclude(x => x.Denials) .AsNoTracking().ToList();
场景说明:Denials通过ReferenceId和ReferenceType关联多个对象,示例中Order 1有一个关联的Denial,Order 2的一条OrderLine也关联了一个Denial。EF生成的SQL正确使用鉴别器查询,结果集包含预期数据,但最终返回的对象中Denials列表始终为空。疑问:该场景是否可行?是否因无外键导致EF忽略填充?
分析与解决
这个场景是可行的,并非无外键导致EF忽略填充,问题出在关联配置未结合鉴别器做过滤,导致EF无法正确匹配主实体与对应的Denial子类。
1. 核心问题
当前的HasMany关联仅基于ReferenceId字段建立映射,但没有将ReferenceType鉴别器作为关联条件的一部分。EF无法区分哪些Denial属于Order、哪些属于OrderLine,即使SQL查询返回了正确数据,也无法将结果映射到对应的Denials集合中。
2. 修正关联配置
需要在配置主实体与Denial的关联时,加入基于ReferenceType的过滤条件,明确指定只有鉴别器匹配的记录才属于当前主实体的集合:
修改OrderConfiguration:
public partial class OrderConfiguration : IEntityTypeConfiguration<Order> { public void Configure(EntityTypeBuilder<Order> entity) { entity.ToTable(nameof(Order)); entity.HasMany(e => e.Denials) .WithOne() .HasForeignKey(e => e.ReferenceId) .HasPrincipalKey(e => e.OrderId) // 加入鉴别器过滤条件 .HasFilter($"[{nameof(Denial.ReferenceType)}] = '{nameof(Order)}'"); } }
修改OrderLineConfiguration:
public partial class OrderLineConfiguration : IEntityTypeConfiguration<OrderLine> { public void Configure(EntityTypeBuilder<OrderLine> entity) { entity.ToTable(nameof(OrderLine)); entity.HasMany(e => e.Denials) .WithOne() .HasForeignKey(e => e.ReferenceId) .HasPrincipalKey(e => e.OrderLineId) // 加入鉴别器过滤条件 .HasFilter($"[{nameof(Denial.ReferenceType)}] = '{nameof(OrderLine)}'"); } }
3. 额外验证点
- 确保鉴别器的
HasValue设置与过滤条件的字符串完全一致,比如HasValue<OrderDenial>(nameof(Order))和过滤中的'{nameof(Order)}'拼写、大小写完全匹配(若数据库区分大小写需特别注意)。 - 检查数据库中
ReferenceType字段的实际值是否与配置一致,避免因数据值不匹配导致映射失败。
内容的提问来源于stack exchange,提问作者Bishop
相关产品推荐
相关产品推荐

