I am trying to eager load properties from elements of a collection which itself is a property of another class. The elements of the collection are polymorphic, not sharing the properties I am trying to include, and tracked in the DB via TPH (Table-per-Hierachry). When I try to eager load them an exception is thrown stating that the base class does not contain the requested property.
I have an abstract base class Base and two derived classes DerivedA and DerivedB. Base has been configured for TPH like this
internal static void Configure(ModelBuilder builder)
{
// Get the EntityTypeBuilder from the given ModelBuilder
EntityTypeBuilder<Base> entityBuilder = builder.Entity<Base>();
// Configure TPH
entityBuilder.ToTable("Bases").HasDiscriminator<int>("DerivedType")
.HasValue<DerivedA>(0)
.HasValue<DerivedB>(1);
}
Furthermore I have a class ToBeLoaded with a property public ICollection<Base> Bases {get; set; } which does contain both DerivedA and DerivedB. I am expecting EF Core to be able to handle this. Am I wrong with that?
The EF Core Docs say I can use as or a direct cast within ThenInclude() like I do in my extension method.
public static IQueryable<ToBeLoaded> LoadRelated(this DbSet<ToBeLoaded> toBeLoadedSet)
{
return toBeLoadedSet.Include(tbl => tbl.Bases)
.ThenInclude(b => (b as DerivedA).PropA)
.Include(tbl => tbl.Bases)
.ThenInclude(b => (b as DerviedB).PropB);
}
When then calling context.ToBeLoadedSet.LoadRelated.ToList(); the following exception is thrown
System.InvalidOperationException: 'The property 'PropA' is not a navigation property of entity type 'Base'. The 'Include(string)' method can only be used with a '.' separated list of navigation property names.'
I already tried to use the other ways to achieve this suggested in the docs, namely direct cast and the Include(string) method.
I am aware that this is somewhat different from the example in the docs, but that is the closest thing to my situation I could find.
Is this even theoretically possible using the Include interface or should I just try to use RawSQL?
So after writing the whole question up I tried one more thing. Just including
BasesliketoBeLoadedSet.Include(tbl => tbl.Bases). For some reason I thought I tried this before and thenPropAandProbBwherenull, but just wanted to be sure.Since it's there now anyways and it might prevent someone else from wasting their time, I will just post it. Thanks for being my rubber duck.
To be clear, the
LoadRelatedmethod looks like this now