1

I have a question about inheritance strategies with the code first approach of entity framework.

Currently i have to implement a variety of question tables to our database.

This is my current QuestionBase class, which has all the properties every type of question needs.

public class QuestionBase 
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int QuestionId { get; set; }

    [Required]
    public QuestionType QuestionType { get; set; }

    public string ShortDescription { get; set; } = string.Empty;

    [Required(AllowEmptyStrings = true)]
    public string QuestionText { get; set; } = string.Empty;

    [Required] 
    public double MaxScore { get; set; }

    public bool MixedAnswers { get; set; } = true;
}

At the moment i have only two different types of questions: SingleChoice and MultipleChoice. The only difference between those types is the navigation property as shown here:

public class SingleChoiceQuestion : QuestionBase
{
    public virtual List<SingleChoiceAnswer> Answers { get; set; }
}
public class MultipleChoiceQuestion : QuestionBase
{
    public virtual List<MultipleChoiceAnswer> Answers { get; set; }
}

My current approach results in table per hierarchie inheritance. As soon as i add a new question type, which contains additional properties, the QuestionBase table will be expanded by additional columns. This is not what i want.

Table per type inheritance is not an option, because i do not know how many different question types will be added in future. I am afraid, the amount of different question types could result in performance issues.

Table per concrete class inheritance is also not what i want.

I also thought about working without inheritance, but with foreign keys and navigation properties instead. But then i realised that at least my first two questions types would result in additional tables with a foreign key for the QuestionBase table only, because they have no additional properties. This does not seem right.

May be there is any other approach i could try?

iButters
  • 39
  • 4
  • "Then don't add it to the base class." I meant the QuestionTable will be expanded when i add another subclass with its own properties. – iButters Apr 02 '21 at 22:42
  • Missed the 5 minutes limitiation for editing comment... Would it not be better to use table per class inheritance? Because this would also result in a table for each entity. And i can still benefit from inheritance (e.g. having a list with entries from all tables, referencing the base class in other entities, etc.). – iButters Apr 02 '21 at 22:54
  • Yes, this results in only one table: "QuestionBase". That is because the column "QuestionType" is the discriminator. This way entity framework distinguishes between "SingleChoiceQuestion" and "MultipleChoiceQuestion" by the value of the column. Let's say i tell ef to get all "SingleChoiceQuestions" from the db, then it will only get those who have the value "1" for the "QuestionType" column. I should have mentioned this in my question. But i do not want to go this way anyway. – iButters Apr 02 '21 at 23:37
  • Sorry, I didn't knew 'TPH'. To me it seems like someone thought it was very cool, but just invented it to omit a few key strokes. I don't find it adding much comfort in coding, more like more complexity. Maybe someone can explain why it is handy instead of just writing blogs about that you can use it to solve a problem there is not until you are trying to implement it. I should write my own SO question I guess. ;) – Silvermind Apr 03 '21 at 00:24
  • The key word is mapping, i guess. I could tell ef to give me all `QuestionBase`-Entities and i will get a list with all `SingleChoiceQuestion`- and `MultipleChoiceQuestion`-Rows. I can even cast an item from the list to it's specific type and use all it's properties without calling the db again. It is also possible to tell it to add a `QuestionBase`-Object but passing a `SingleChoiceQuestion`-Object (it will be recognized as SingleChoiceQuestion). This would save me a lot of ifs and switches. TPT would be the most clean approach, in terms of normalization, but is performance hungry af. – iButters Apr 04 '21 at 12:45

0 Answers0