Dimitri
Dimitri

Reputation: 1271

Entity Framework Inheritance relational tables

I have tried several things before coming here, such as different model approach, annotation, declarations in DbContext, different fluent API usages but I can't seem to see what the issue is.

I have a YogaClass record but when I iterate over the subscriptions from a person, I have a subscription but no YogaClass (NULL) and yes I.Include(Person.Subscriptions) when querying the DB, I'm getting the subs but not the relational YogaClass/WorkShop associated with it.

In short, I have the following classes :

Subscription (base class)

public class Subscribtion
{
    [Key]
    public int SubscribtionID { get; set; }

    public Person Person { get; set; }
    public bool IsPayed { get; set; }
}

WorkshopSubscription (inherrits Subscription)

public class WorkshopSubscribtion : Subscribtion
{
    [Key] 
    public int WorkshopSubscribtionID { get; set; }
    public Workshop Workshop { get; set; }
}

YogaClassSubscription (inherrits Subscription)

public class YogaClassSubscribtion : Subscribtion
{
    [Key] 
    public int YogaClassSubscribtionID { get; set; }
    public YogaClass YogaClass { get; set; }
}

YogaClass (base class)

public class YogaClass
{
    [Key]
    public int YogaClassID { get; set; }
    public List<Subscriptions> Subscriptions { get; set; }
}

WorkShop (base class)

public class WorkShop
{
    [Key]
    public int WorkShopID { get; set; }
    public List<Subscriptions> Subscriptions { get; set; }
}

Now after I insert some records in the Seeder I have the following issue when I look into my DataBase:

Table Subscription : SubscriptionID:1 , WorkShop_WorkShopID:NULL , YogaClass_YogaClassID:NULL . (Why are they both NULL ?) enter image description here

Table YogaClassSubscription : SubscriptionID:1 , YogaClassID:1 enter image description here Same for workshop.

I don't get why the FK from Yoga & Workshop Subscription is NULL in Subscription table.

I have a DbSet declared in my Context and in modelBuilder fluent API method I have mapped both YogaClassSubscribtion & WorkShopSubscribtion to their own table.

public DbSet<Subscribtion> Subscribtions { get; set; }       
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<WorkshopSubscribtion>().ToTable("WorkshopSubscribtions");
    modelBuilder.Entity<YogaClassSubscribtion>().ToTable("YogaClassSubscribtions");
}

Upvotes: 0

Views: 75

Answers (1)

Diana
Diana

Reputation: 2226

I think your problem comes from using the base class Subscription as the type of your generic lists Subscriptions. You should use the specific derived classes YogaClassSubscription and WorkShopSubscription:

public class YogaClass
{
    [Key]
    public int YogaClassID { get; set; }
    public virtual List<YogaClassSubscription> Subscriptions { get; set; }
}

public class WorkShop
{
    [Key]
    public int WorkShopID { get; set; }
    public virtual List<WorkShopSubscription> Subscriptions { get; set; }
}

This way EF knows about the relationship between WorkShops and WorkShopSubscriptions, and between YogaClasses and YogaClassSubscriptions.

Another thing that seems wrong: redefining the ID property and the Key annotations in your derived classes. You only need to define the ID in the base class. Remove those properties and their annotations. EF will create a foreign key with a one-to-one relationship between your base class table and the derived classes tables.

public class WorkshopSubscription : Subscription
{
    public virtual Workshop Workshop { get; set; }
}

public class YogaClassSubscription : Subscription
{
    public virtual YogaClass YogaClass { get; set; }
}

An advice: define your navigation properties as virtual, in order to allow EF to use proxies to track status changes in your entities, and also to allow the use of Lazy Loading.

Upvotes: 1

Related Questions