Reputation: 3654
In my example, I have a Farm
with Animals
. The Animals
within my collection is <Animal, Dog, Cat>
. Dog
& Cat
inherit from Animal.
When loading theFarm
entity. How can I make Entity Framework load my instances as their respective subtypes <Animal, Dog, Cat>
instead of <Animal, Animal, Animal>
?
var farm = new Farm();
farm.Animals.Add(new Animal { Name = "Parrot" });
farm.Animals.Add(new Dog { Name = "Waffles", FavoriteToy = "slinky" });
farm.Animals.Add(new Cat { Name = "Pitou", FavoriteFood = "Salmon" });
using Microsoft.EntityFrameworkCore;
public class Program
{
public static void Main(string[] args)
{
var p = new Program();
p.CreateFarm();
p.Display();
}
public void CreateFarm()
{
using var context = new MyContext();
if (context.Farms.FirstOrDefault() == null)
{
var farm = new Farm();
farm.Animals.Add(new Animal { Name = "Parrot" });
farm.Animals.Add(new Dog { Name = "Waffles", FavoriteToy = "slinky" });
farm.Animals.Add(new Cat { Name = "Pitou", FavoriteFood = "Salmon" });
context.Farms.Add(farm);
context.SaveChanges();
}
}
public void Display()
{
using var context = new MyContext();
var animals = context.Farms.Include(f => f.Animals).First().Animals;
foreach (var a in animals)
{
var txt = $"animal of type : {a.GetType().Name}";
if (a is Dog or Cat)
{
txt += ". It's a pet!";
}
Console.WriteLine(txt);
}
}
}
public class MyContext : DbContext
{
public DbSet<Farm> Farms { get; set; }
public DbSet<Animal> Animals{ get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlite("Data Source=c:\\temp\\mydb.db;");
}
}
public class Farm
{
public int ID { get; set; }
public virtual ICollection<Animal> Animals { get; set; } = new HashSet<Animal>();
}
public class Animal
{
public int ID { get; set; }
public int? FarmID { get; set; }
public string Name { get; set; }
public virtual Farm? Farm { get; set; }
}
public class Dog : Animal {
public string FavoriteToy { get; set; }
}
public class Cat : Animal
{
public string FavoriteFood { get; set; }
}
Upvotes: 2
Views: 62
Reputation: 17485
Here How I configured context.
public class MyContext : DbContext
{
public DbSet<Farm> Farms { get; set; }
public DbSet<Animal> Animals { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlite("Data Source=c:\\temp\\mydb.db;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Animal>()
.HasDiscriminator<string>("AnimalType")
.HasValue<Animal>("animal")
.HasValue<Dog>("animal_dog")
.HasValue<Cat>("animal_cat");
}
}
public class Farm
{
public int ID { get; set; }
public virtual ICollection<Animal> Animals { get; set; } = new HashSet<Animal>();
}
public class Animal
{
public int ID { get; set; }
public int? FarmID { get; set; }
public string Name { get; set; }
public virtual Farm? Farm { get; set; }
}
public class Dog : Animal
{
public string FavoriteToy { get; set; }
}
public class Cat : Animal
{
public string FavoriteFood { get; set; }
}
From above code if you look at the configure.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Animal>()
.HasDiscriminator<string>("AnimalType")
.HasValue<Animal>("animal")
.HasValue<Dog>("animal_dog")
.HasValue<Cat>("animal_cat");
}
Here few things.
Example or demo code is similar to what is in the question so I am not repeating that over here.
Upvotes: 1