Note. The example below is known as Table-Per-Hierarchy (TPH) - that is, all contained in a single table. Click this link for Table-Per-Type (TPT) , which has different tables for each type.
When using base types and inherited types, you must tell EF how to define an association for a specific inherited type.
Taking your code:
public abstract class SelfReferencing { public SelfReferencing Parent { get; set; } public ICollection<SelfReferencing> Children { get; set; } } public class ConcreteSelfReferencing : SelfReferencing { }
Now EF must decide whether the subclass is a ConcreteSelfReferencing class or any other type of subclass. This is determined by the discriminator of the table itself, to which the column is not part of your mapping.
To take another example, similar to the one I used in the past:
public abstract class Policy { public int Id { get; set; } public string PolicyNumber { get; set; } } public class InsurancePolicy : Policy { } public class CarPolicy : Policy { }
The table was structured as follows:
| Id | PolicyNumber | Type | ..... | 1 CAR0001 C 2 ISN0001 I
To get the EF, to bring them correctly, you would get:
public class MyContext : DbContext { public MyContext() : base() { } public DbSet<Policy> Policies { get; set; } protected override void OnModelCreating(ModelBuilder builder) { var policyMap = modelBuilder.Entity<Policy>();
And from your code, you can do the filtering yourself or put the filtering in the DbContext . Here is an example from a separate class.
public class PolicyRepository { private MyContext context = new MyContext(); public PolicyRepository() { } public IQueryable<InsurancePolicy> GetInsurancePolicies() { return this.context.Policies.OfType<InsurancePolicy>(); } public IQueryable<CarPolicy> GetCarPolicies() { return this.context.Policies.OfType<CarPolicy>(); } }