C# 因为它确实回答了原来的问题。如果你不介意的话,你能更新你的答案来解决第二个问题吗?我感谢你的帮助!不客气。但现在你似乎把TPH和TPT混为一谈,这是你的意图吗?i、 e.ObjectiveQuestionOption正在从其基础ObjectiveQuest

C# 因为它确实回答了原来的问题。如果你不介意的话,你能更新你的答案来解决第二个问题吗?我感谢你的帮助!不客气。但现在你似乎把TPH和TPT混为一谈,这是你的意图吗?i、 e.ObjectiveQuestionOption正在从其基础ObjectiveQuest,c#,entity-framework,ef-fluent-api,tph,C#,Entity Framework,Ef Fluent Api,Tph,因为它确实回答了原来的问题。如果你不介意的话,你能更新你的答案来解决第二个问题吗?我感谢你的帮助!不客气。但现在你似乎把TPH和TPT混为一谈,这是你的意图吗?i、 e.ObjectiveQuestionOption正在从其基础ObjectiveQuestion(TPH)共享TPH,但其他列也会转到另一个表TB\u OBJECTIVE\u QUESTION\u OPTION(TPT)。因为如果是这样,不将公共语句列映射到新表是正常的,因为它将从基表中获取。是的,基本上就是这样。我之所以选择con


因为它确实回答了原来的问题。如果你不介意的话,你能更新你的答案来解决第二个问题吗?我感谢你的帮助!不客气。但现在你似乎把TPH和TPT混为一谈,这是你的意图吗?i、 e.
ObjectiveQuestionOption
正在从其基础
ObjectiveQuestion
(TPH)共享TPH,但其他列也会转到另一个表
TB\u OBJECTIVE\u QUESTION\u OPTION
(TPT)。因为如果是这样,不将公共
语句
列映射到新表是正常的,因为它将从基表中获取。是的,基本上就是这样。我之所以选择configs继承(以及泛型)是因为
答案
configs使用了TPT(我没有提到它们,因为它们不是这样)。但是假设
Question
只有一个成员,我们从
QuestionConfiguration
中删除了他的映射,那么拥有它有什么意义呢?我不清楚,你能给我举个例子吗?一旦一个类被标识为实体,即使你没有为属性包含特定的映射,它也会按照约定映射到相应的基表,并且不能重新映射到另一个表。如果在基本实体中确实
忽略它,则无法在任何派生实体中映射它。因此,最好只在层次结构的每个级别映射已声明的属性。
// Base class for any kind of question
public abstract class Question : Bean
{
    public string Statement { get; set; }
}

// Visual questions are questions where images are answers.
public class VisualQuestion : Question
{
    public virtual VisualAnswer Answer { get; set; }
}

// Discursive questions are questions where big texts are answers.
public class DiscursiveQuestion : Question
{
    public virtual DiscursiveAnswer Answer { get; set; }
}

// Objective questions are questions that can have multiple answers,
// where each of them should be no bigger than 1 character.
public class ObjectiveQuestion : Question
{
    public virtual List<ObjectiveQuestionOption> Options { get; set; }
}

// Options for objective questions.
public class ObjectiveQuestionOption : Question
{
    public int ObjectiveQuestionId { get; set; }

    public virtual ObjectiveQuestion Question { get; set; }

    public virtual ObjectiveAnswer Answer { get; set; }
}
public abstract class Answer : Bean
{
    public int QuestionId { get; set; }
}

public class DiscursiveAnswer : Answer
{
    public string Answer { get; set; }

    public virtual DiscursiveQuestion Question { get; set; }
}

public class ObjectiveAnswer : Answer
{
    public char Answer { get; set; }

    public virtual ObjectiveQuestion Question { get; set; }
}

public class VisualAnswer : Answer
{
    public byte[] Blob { get; set; } // Image answer

    public virtual VisualQuestion Question { get; set; }
}
public abstract class Bean 
{
    public int Id { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // Approach 1: This works
    //modelBuilder.Entity<Question>().Map<DiscursiveQuestion>(p => p.Requires("TP_QUESTION").HasValue("D")).ToTable("TB_QUESTION");
    //modelBuilder.Entity<Question>().Map<ObjectiveQuestion>(p => p.Requires("TP_QUESTION").HasValue("O")).ToTable("TB_QUESTION");
    //modelBuilder.Entity<Question>().Map<VisualQuestion>(p => p.Requires("TP_QUESTION").HasValue("V")).ToTable("TB_QUESTION");

    // Approach 2: This does not work: it complains that 2 of the 3 entities cant share the TB_QUESTION table because "they are not in the same type hierarchy 
    // or do not have a valid one to one foreign key relationship with matching primary keys between them" (???).
    modelBuilder.Configurations.Add(new VisualQuestionConfiguration());
    modelBuilder.Configurations.Add(new ObjectiveQuestionConfiguration());
    modelBuilder.Configurations.Add(new DiscursiveQuestionConfiguration());
}
public abstract class QuestionConfiguration<T> : EntityTypeConfiguration<T> where T : Question
{
    public QuestionConfiguration()
    {
        Property(p => p.Statement).HasColumnName("STATEMENT");
    }
}

public class DiscursiveQuestionConfiguration : QuestionConfiguration<DiscursiveQuestion>
{
    public DiscursiveQuestionConfiguration()
    {
        Map(p => p.Requires("TP_QUESTION").HasValue("D")).ToTable("TB_QUESTION");
    }
}

public class VisualQuestionConfiguration : QuestionConfiguration<VisualQuestion>
{
    public VisualQuestionConfiguration()
    {
        Map(p => p.Requires("TP_QUESTION").HasValue("V")).ToTable("TB_QUESTION");
    }
}

public class ObjectiveQuestionConfiguration : QuestionConfiguration<ObjectiveQuestion>
{
    public ObjectiveQuestionConfiguration()
    {
        Map(p => p.Requires("TP_QUESTION").HasValue("O")).ToTable("TB_QUESTION");
    }
}
public class QuestionConfiguration : EntityTypeConfiguration<Question>
{
    public QuestionConfiguration()
    {
        Property(p => p.Statement).HasColumnName("STATEMENT");

        // Configures the TPH
        Map<VisualQuestion>(p => p.Requires("TYPE").HasValue("Visual").HasMaxLength(10));
        Map<ObjectiveQuestion>(p => p.Requires("TYPE").HasValue("Objective").HasMaxLength(10));
        Map<DiscursiveQuestion>(p => p.Requires("TYPE").HasValue("Discursive").HasMaxLength(10));

        ToTable("TB_QUESTION");
    }
}

public class DiscursiveQuestionConfiguration : Configuration<DiscursiveQuestion>
{
    public DiscursiveQuestionConfiguration()
    {
    }
}

public class VisualQuestionConfiguration : Configuration<VisualQuestion>
{
    public VisualQuestionConfiguration()
    {
    }
}

public class ObjectiveQuestionConfiguration : Configuration<ObjectiveQuestion>
{
    public ObjectiveQuestionConfiguration()
    {
    }
}

public class ObjectiveQuestionOptionConfiguration : Configuration<ObjectiveQuestionOption>
{
    public ObjectiveQuestionOptionConfiguration()
    {
        HasRequired(p => p.Question).WithMany(p => p.Options).HasForeignKey(p => p.ObjectiveQuestionId);

        Property(p => p.ObjectiveQuestionId).HasColumnName("ID_OBJECTIVE_QUESTION");
        Property(p => p.Statement).HasColumnName("STATEMENT"); // <--- This doesnt get mapped! :(

        ToTable("TB_OBJECTIVE_QUESTION_OPTION");
    }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // Approach 1: This works
    //modelBuilder.Entity<Question>().Map<DiscursiveQuestion>(p => p.Requires("TP_QUESTION").HasValue("D")).ToTable("TB_QUESTION");
    //modelBuilder.Entity<Question>().Map<ObjectiveQuestion>(p => p.Requires("TP_QUESTION").HasValue("O")).ToTable("TB_QUESTION");
    //modelBuilder.Entity<Question>().Map<VisualQuestion>(p => p.Requires("TP_QUESTION").HasValue("V")).ToTable("TB_QUESTION");

    // Approach 2: This does work too, however ObjectiveQuestionOption* does not inherit the statement column
    modelBuilder.Configurations.Add(new QuestionConfiguration());
    modelBuilder.Configurations.Add(new QuestionOptionConfiguration());
}
public class QuestionConfiguration : EntityTypeConfiguration<Question>
{
    public QuestionConfiguration()
    {
        Property(p => p.Statement).HasColumnName("STATEMENT");
        ToTable("TB_QUESTION");
    }
}

public class DiscursiveQuestionConfiguration : EntityTypeConfiguration<DiscursiveQuestion>
{
    public DiscursiveQuestionConfiguration()
    {
        Map(p => p.Requires("TP_QUESTION").HasValue("D"));
    }
}

public class VisualQuestionConfiguration : EntityTypeConfiguration<VisualQuestion>
{
    public VisualQuestionConfiguration()
    {
        Map(p => p.Requires("TP_QUESTION").HasValue("V"));
    }
}

public class ObjectiveQuestionConfiguration : EntityTypeConfiguration<ObjectiveQuestion>
{
    public ObjectiveQuestionConfiguration()
    {
        Map(p => p.Requires("TP_QUESTION").HasValue("O"));
    }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Configurations.Add(new QuestionConfiguration());
    modelBuilder.Configurations.Add(new VisualQuestionConfiguration());
    modelBuilder.Configurations.Add(new ObjectiveQuestionConfiguration());
    modelBuilder.Configurations.Add(new DiscursiveQuestionConfiguration());
}