Question

I am working on an Entity Framework Code First project and having some issues creating mappings. A little background:

The database will be used for an online survey demo. For the purposes of this question, it's useful to know that we have Question and QuestionAnswerOption entities. On the question entity we need to first know the available QuestionAnswerOptions for the currrent question. Second, we would like to know if there is a pre-requisite question and then if there is we need to know what are the acceptable QuestionAnswerOptions from the pre-req question that allow this question to be displayed or hidden.

Hopefully this makes sense, but I will put some mock code so you can see pretty much what we've got so far.

public class Question
{
    public virtual List<QuestionAnswerOption> AvailableQuestionAnswerOptions { get; set; }
    public Question RequiredPrerequisiteQuestion { get; set; }
    public virtual List<QuestionAnswerOption> AcceptablePrerequisiteQuestionAnswerOptions { get; set; }
}

public class QuestionAnswerOption
{
    public int Index { get;set; }
    public string Value { get;set; } // this may be 'Yes', 'No', 'Maybe', 'Don't Know', etc.
    public virtual List<Question> Questions { get; set; }
}

// then inside of our database context class we have the following
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

    modelBuilder.Entity<Question>().HasMany(x =>
        x.AvailableQuestionAnswerOptions).WithMany(y => y.Questions)
        .Map(m =>
        {
            m.MapLeftKey("Question_ID");
            m.MapRightKey("QuestionAnswerOption_ID");
            m.ToTable("AvailableQuestionAnswerOptionMap");
        });

    modelBuilder.Entity<Question>().HasMany(x =>
        x.AcceptablePrerequisiteQuestionAnswerOptions).WithMany(y => y.Questions)
        .Map(m =>
        {
            m.MapLeftKey("Question_ID");
            m.MapRightKey("QuestionAnswerOption_ID");
            m.ToTable("AcceptableQuestionAnswerOptionMap");
        });
}

When trying to create the migration after doing this we get the following error:

Schema specified is not valid. Errors: The relationship 'XYZ.Database.Question_AvailableQuestionAnswerOptions' was not loaded because the type 'XYZ.Database.QuestionAnswerOption' is not available.

However, if we comment out either of the 2 modelBuilder.Entity<> calls the migration runs through smoothly. Is there a way to get both of these to work at the same time? Or more importantly, is there a better way to do what we're trying to do with EF Code First?

Thanks

Was it helpful?

Solution

I was able to figure this out after sleeping on it. So for anyone else that runs into a similar situation here's the new code.

// No change to this class
pubic class Question
{
    public virtual List<QuestionAnswerOption> AvailableQuestionAnswerOptions { get; set; }
    public Question RequiredPrerequisiteQuestion { get; set; }
    public virtual List<QuestionAnswerOption> AcceptablePrerequisiteQuestionAnswerOptions { get; set; }
}

// Added second collection of Question, PreRequisiteQuestions
public class QuestionAnswerOption
{
    public int Index { get;set; }
    public string Value { get;set; } // this may be 'Yes', 'No', 'Maybe', 'Don't Know', etc.
    public virtual List<Question> Questions { get; set; }
    public virtual List<Question> PreRequisiteQuestions { get; set; }
}

// then inside of our database context class we have the following
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

    modelBuilder.Entity<Question>().HasMany(x =>
        x.AvailableQuestionAnswerOptions).WithMany(y => y.Questions)
        .Map(m =>
        {
            m.MapLeftKey("Question_ID");
            m.MapRightKey("QuestionAnswerOption_ID");
            m.ToTable("AvailableQuestionAnswerOptionMap");
        });

    // changed this to use the new PreRequisiteQuestions collection
    modelBuilder.Entity<Question>().HasMany(x =>
        x.AcceptablePrerequisiteQuestionAnswerOptions).WithMany(y => y.PreRequisiteQuestions )
        .Map(m =>
        {
            m.MapLeftKey("Question_ID");
            m.MapRightKey("QuestionAnswerOption_ID");
            m.ToTable("AcceptableQuestionAnswerOptionMap");
        });
}

This got me the results I was looking for, though I'm still interested to know if there is a better way to do this?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top