We found a solution with inheritance as described in Microsoft documentation. There is an example showing a simple inheritance scenario and the data stored in a relational database table using the table-per-hierarchy pattern. The Discriminator column identifies which type of Blog is stored in each row. Our projects looks as follows:
BaseContext.cs
using Microsoft.EntityFrameworkCore;
namespace Base.Data
{
public partial class BaseContext : DbContext
{
public BaseContext()
{
}
public BaseContext(DbContextOptions<BaseContext> options)
: base(options)
{
}
public virtual DbSet<Tab1> Tab1 { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer("Server=.\\SQLEXPRESS2017;Database=base;Trusted_Connection=True;");
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Tab1>(entity =>
{
entity.Property(e => e.Id)
.HasColumnType("numeric(18, 0)")
.ValueGeneratedOnAdd();
entity.Property(e => e.Col1).HasMaxLength(50);
});
}
}
}
ExtendedContext.cs
using System;
using Microsoft.EntityFrameworkCore;
using Base.Data;
using System.Linq;
using Microsoft.EntityFrameworkCore.SqlServer.Infrastructure.Internal;
namespace Extended.Data
{
public partial class ExtendedContext : BaseContext
{
protected static DbContextOptions<T> ChangeOptionsType<T>(DbContextOptions options) where T : DbContext
{
var sqlExt = options.Extensions.FirstOrDefault(e => e is SqlServerOptionsExtension);
if (sqlExt == null)
throw (new Exception("Failed to retrieve SQL connection string for base Context"));
return new DbContextOptionsBuilder<T>()
.UseSqlServer(((SqlServerOptionsExtension)sqlExt).ConnectionString)
.Options;
}
public ExtendedContext()
{
}
public ExtendedContext(DbContextOptions<ExtendedContext> options)
: base(ExtendedContext.ChangeOptionsType<BaseContext>(options))
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Tab1>(entity =>
{
entity.Property(e => e.Col2).HasMaxLength(50);
});
modelBuilder.Entity<Base.Data.Tab1>()
.HasDiscriminator<bool>("IsExtended")
.HasValue<Base.Data.Tab1>(false)
.HasValue<Tab1>(true);
modelBuilder.Entity<Tab2>()
.HasOne(p => p.Tab1)
.WithMany(b => b.Tab2)
.HasForeignKey(p => p.Tab1Id)
.HasConstraintName("ForeignKey_Tab1_Tab2");
modelBuilder.Entity<Tab2>(entity =>
{
entity.Property(e => e.Id)
.HasColumnType("numeric(18, 0)")
.ValueGeneratedOnAdd();
entity.Property(e => e.Col1).HasColumnType("numeric(18, 0)");
});
}
public new virtual DbSet<Tab1> Tab1 { get; set; }
public virtual DbSet<Tab2> Tab2 { get; set; }
}
}