Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
536 views
in Technique[技术] by (71.8m points)

ef code first - Entity Framework Core - get rid of duplicate id of inherited object

I'm using PostgreSQL database with the EF Core (with the Table-Per-Type inheritance).

I have questions and question items (in this case, options for answering a question). Any question must have an Id, Text and Cost. Question item must have an Id, Text and QuestionId (id of the question to which it belongs). Some questions (e.g. MultipleChoiceQuestion) contain question items and some don't (e.g. TextQuestion).

Each QuestionItem has a QuestionId and MultipleChoiceQuestionAnswerOption can only be used with MultipleChoiceQuestion. So I want to have a navigation property inside the MultipleChoiceQuestionAnswerOption that refers the corresponding MultipleChoiceQuestion. I know that if MultipleChoiceQuestionAnswerOption can only be used with MultipleChoiceQuestion, then MultipleChoiceQuestionAnswerOption.QuestionId always references the Question which is actually MultipleChoiceQuestion. But I don't know how to set this up with EF Core.

I want to have entities like the following:

public class abstract Question
{
    public Guid Id { get; set; }
    public string Text { get; set; }
    public int Cost { get; set; }
    public ICollection<QuestionItem> Items { get; set; }
}

public class TextQuestion : Question
{
    public string CorrectAnswer { get; set; }
}

public class MultipleChoiceQuestion : Question
{
    public ICollection<MultipleChoiceQuestionAnswerOption> AnswerOptions { get; set; }
}

public abstract class QuestionItem
{
    public Guid Id { get; set; }
    public string Text { get; set; }
    public Guid QuestionId { get; set; }
    public Question Question { get; set; }
}

public class MultipleChoiceQuestionAnswerOption : QuestionItem
{
    public bool IsCorrect { get; set; }
    public MultipleChoiceQuestion MultipleChoiceQuestion { get; set; }
}

With the following relation configurations:

questionBuilder
    .HasMany(question => question.Items)
    .WithOne(questionItem => questionItem.Question)
    .HasForeignKey(questionItem => questionItem.QuestionId);

multipleChoiceQuestionBuilder
    .HasMany(question => question.AnswerOptions)
    .WithOne(answerOption => answerOption.MultipleChoiceQuestion)
    .HasForeignKey(answerOption => answerOption.QuestionId);

I've tried leaving it like this, but when staring the application I get this error message:

The foreign key {'QuestionId'} on the entity type 'MultipleChoiceQuestionAnswerOption' targeting 'MultipleChoiceQuestion' cannot be represented in the database. Either the properties {'QuestionId'} aren't mapped t o table 'multiple_choice_question_answer_options' or the principal properties {'Id'} aren't mapped to table 'multiple_choice_questions'. All foreign key properties must map to the table that the dependent type is mapped to and a ll principal properties must map to a single table that the principal type is mapped to.

My guess is that you need to provide a separate foreign key property for each navigation property. But in this case, the interface of the MultipleChoiceQuestionAnswerOption entity will look something like this:

Guid Id { get; set; }
string Text { get; set; }
bool IsCorrect { get; set; }

Guid QuestionId { get; set; }
Guid MultipleChoiceQuestionId { get; set; }

Question Question { get; set; }
MultipleChoiceQuestion MultipleChoiceQuestion { get; set; }

And the values of the QuestionId and MultipleChoiceQuestionId fields will always be the same (since MultipleChoiceQuestionAnswerOption can only be used with MultipleChoiceQuestion). I want to get rid of this duplication, but not sure how exactly.

What configuration should be applied to reuse the QuestionId field for both the base Question type and the derived MultipleChoiceQuestion type?

question from:https://stackoverflow.com/questions/65950734/entity-framework-core-get-rid-of-duplicate-id-of-inherited-object

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...