Summary
I am trying to use Inheritance to Hierarchy inheritance in combination with the one-to-many relationship in a .Net Core 1.1 project. Both the parent and child objects use inheritance. I have a very simple entity model. I have one basic parent object: Session , which has two objects that extend from it: QuotingSession and BackOfficeSession . Both of these parent objects contain a set of child entities (one-to-many relationship). In addition, child objects are created using inheritance. There is a base child: Policy . This base child object is extended by two objects: QuotingPolicy and BackOfficePolicy. When I create any of the parent objects and try to save, I get this exception:
InvalidCastException: Unable to cast object of type 'EFTest.QuotingSession' to type 'EFTest.BackOfficeSession
However, when I tell the entity structure to ignore one of the child collections on either of the parents, persistence works for both parent objects without exception. For instance:
var entity = modelBuilder.Entity<BackOfficeSession>();
entity.Ignore(c => c.Policies);
In addition, if I did not configure one of the parents (QuotingSession) at all and just saved the other parent (BackOfficeSession), it saves everything as freed.
Repo
https://github.com/seantarogers/EFTest
More details
I use Microsoft.EntityFrameworkCore 1.1.1
and Microsoft.EntityFrameworkCore.SqlServer 1.1.1
in the project .Net core 1.1
.
I have the following simple database schema:

My classes are as follows:
1. Session
namespace EFTest
{
public abstract class Session
{
public int Id { get; private set; }
}
}
2. QuotingSession
using System.Collections.Generic;
namespace EFTest
{
public class QuotingSession : Session
{
public string QuotingName { get; private set; }
public List<QuotingPolicy> Policies { get; private set; }
private QuotingSession()
{
}
public QuotingSession(string name, List<QuotingPolicy> quotingPolicies)
{
QuotingName = name;
Policies = quotingPolicies;
}
}
}
3. BackOfficeSession
using System.Collections.Generic;
namespace EFTest
{
public class BackOfficeSession : Session
{
public List<BackOfficePolicy> Policies { get; private set; }
public string BackOfficeName { get; private set; }
private BackOfficeSession()
{
}
public BackOfficeSession(string name, List<BackOfficePolicy> policies)
{
BackOfficeName = name;
Policies = policies;
}
}
}
4. Policy
namespace EFTest
{
public abstract class Policy
{
public int Id { get; set; }
public int SessionId { get; set; }
}
}
5. QuotingPolicy
namespace EFTest
{
public class QuotingPolicy : Policy
{
public string QuotingPolicyName { get; private set; }
private QuotingPolicy()
{
}
public QuotingPolicy(string name)
{
QuotingPolicyName = name;
}
}
}
6. BackOfficePolicy
namespace EFTest
{
public class BackOfficePolicy : Policy
{
public string BackOfficePolicyName { get; private set; }
private BackOfficePolicy()
{
}
public BackOfficePolicy(string name)
{
BackOfficePolicyName = name;
}
}
}
7. EF DB context and free configuration
using Microsoft.EntityFrameworkCore;
namespace EFTest
{
public class TestDbContext : DbContext
{
public TestDbContext(DbContextOptions options)
: base(options)
{
}
public DbSet<QuotingSession> QuotingSessions { get; set; }
public DbSet<BackOfficeSession> BackOfficeSessions { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
ConfigureSession(modelBuilder);
ConfigurePolicy(modelBuilder);
ConfigureQuotingSession(modelBuilder);
ConfigureBackOfficeSession(modelBuilder);
ConfigureBackOfficePolicy(modelBuilder);
ConfigureQuotingPolicy(modelBuilder);
}
public static void ConfigurePolicy(ModelBuilder modelBuilder)
{
var entity = modelBuilder.Entity<Policy>();
entity.ToTable("Policy", "dbo");
entity.HasKey(x => x.Id);
entity.HasDiscriminator<int>("SessionType")
.HasValue<QuotingPolicy>(1)
.HasValue<BackOfficePolicy>(2);
}
public static void ConfigureBackOfficePolicy(ModelBuilder modelBuilder)
{
var entity = modelBuilder.Entity<BackOfficePolicy>();
entity.Property(x => x.BackOfficePolicyName);
}
public static void ConfigureQuotingPolicy(ModelBuilder modelBuilder)
{
var entity = modelBuilder.Entity<QuotingPolicy>();
entity.Property(x => x.QuotingPolicyName);
}
public static void ConfigureSession(ModelBuilder modelBuilder)
{
var entity = modelBuilder.Entity<Session>();
entity.ToTable("Session", "dbo");
entity.HasKey(x => x.Id);
entity.HasDiscriminator<int>("SessionType")
.HasValue<QuotingSession>(1)
.HasValue<BackOfficeSession>(2);
}
public static void ConfigureBackOfficeSession(ModelBuilder modelBuilder)
{
var entity = modelBuilder.Entity<BackOfficeSession>();
entity.Property(x => x.BackOfficeName);
entity.HasMany(c => c.Policies).WithOne().HasForeignKey(c => c.SessionId);
}
public static void ConfigureQuotingSession(ModelBuilder modelBuilder)
{
var entity = modelBuilder.Entity<QuotingSession>();
entity.Property(x => x.QuotingName);
entity.HasMany(c => c.Policies).WithOne().HasForeignKey(c => c.SessionId);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
}
}
}
8. To check it out
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
namespace EFTest
{
class Program
{
static void Main(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder<TestDbContext>();
const string conn = "Server=.\\SqlServer2014;Database=EFTest;Trusted_Connection=True"
optionsBuilder.UseSqlServer(conn);
using (var dbContext = new TestDbContext(optionsBuilder.Options))
{
var quotingPolicy = new QuotingPolicy("quotingPolicyname");
var quotingSession = new QuotingSession("quotingSessionName", new List<QuotingPolicy> {quotingPolicy});
dbContext.QuotingSessions.Add(quotingSession);
dbContext.SaveChanges();
}
}
}
}
thanks for the help