EF Core两层继承场景下LINQ查询中间抽象类属性的问题
问题解答
1. 能否在LINQ查询中使用未加入EF模型的中间抽象类属性?
不行。EF Core的查询翻译完全依赖模型元数据,当前你仅将Animal和具体子类注册到模型中,中间抽象类Mammal并未被EF识别为模型的一部分。这导致EF无法将x is Mammal或(x as Mammal).HasPouch这类表达式翻译成对应SQL逻辑,最终抛出无法翻译的异常。
2. 能否将Mammal加入EF模型且映射到同一Animals表?
完全可以,只需在OnModelCreating中把Mammal配置为实体,并指定鉴别器值,同时保持所有实体映射到同一个Animals表即可。
修改后的DbContext配置代码
public DbSet<Animal> Animals { get; set; } // 若需直接查询Mammal,可添加DbSet<Mammal>,非必须 // public DbSet<Mammal> Mammals { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { // 配置基类Animal及鉴别器 var animalEntity = modelBuilder.Entity<Animal>() .ToTable("Animals") .HasDiscriminator<string>("AnimalType"); // 将Mammal映射到同一Animals表 modelBuilder.Entity<Mammal>() .ToTable("Animals"); // 为所有层级的实体指定鉴别器值 animalEntity .HasValue<Parrot>("Parrot") .HasValue<Mammal>("MammalBase") // 给抽象类Mammal设置鉴别器标识 .HasValue<Dog>("Dog") .HasValue<Cat>("Cat") .HasValue<Horse>("Horse"); // 可选:显式配置HasPouch字段的约束 modelBuilder.Entity<Mammal>() .Property(m => m.HasPouch) .IsRequired(); }
修改后的查询代码
现在可以用更简洁的逻辑查询Mammal的属性:
// 方式1:直接筛选哺乳动物中HasPouch为true的个体 List<Animal> marsupials = context.Animals .OfType<Mammal>() .Where(m => m.HasPouch) .Cast<Animal>() .ToList(); // 方式2:原有的is/as写法也能正常运行 List<Animal> marsupials = context.Animals .Where(x => x is Mammal && (x as Mammal).HasPouch) .ToList();
原理说明
将Mammal注册为EF模型实体后,EF Core会识别它的属性与继承关系,同时所有实体共享Animals表。EF会自动处理鉴别器逻辑,将OfType<Mammal>()翻译成SQL中的WHERE AnimalType IN ('MammalBase', 'Dog', 'Cat', 'Horse'),从而正确筛选所有哺乳动物并查询HasPouch属性。
内容的提问来源于stack exchange,提问作者Pavel Foltyn
相关产品推荐
相关产品推荐

