我不确定我是否理解正确,但我认为您将需要(并且已经拥有)一个many-to-many
on Option/Question
- 另外,您在它们之间还有一个一对多(所有者)关系。
我没有足够的知识来讨论这是否是最好的解决方案——但是相信你的“依赖”关系(和另一个)......
...为此,您需要“微调”您的关系和索引表。EF/CF 在后台创建默认的,我认为你需要的是在流畅的配置中创建关系 - 并自己添加额外的列。
而且我通常建议在代码中进行自己的配置 - 与属性/默认配置 - 就像在任何复杂的场景中一样,它可以为您提供更多选项和控制,更少的错误等。就我而言,我只想知道哪些表和列是为我创建的。
这是一个特定的示例代码(我删除了其他不必要的表,只是 Q/O)...
public class QuestionContext : DbContext
{
public DbSet<Question> Questions { get; set; }
public DbSet<Option> Options { get; set; }
public DbSet<QuestionOption> QuestionOptions { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<QuestionOption>()
.HasKey(i => new { i.OptionID, i.QuestionID });
modelBuilder.Entity<QuestionOption>()
.HasRequired(i => i.Opiton)
.WithMany(u => u.DependencyOptions)
.HasForeignKey(i => i.OptionID)
.WillCascadeOnDelete(false);
modelBuilder.Entity<QuestionOption>()
.HasRequired(i => i.Question)
.WithMany(u => u.DependencyOptions)
.HasForeignKey(i => i.QuestionID)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Option>()
.HasRequired(i => i.Question)
.WithMany(u => u.Options)
.HasForeignKey(i => i.QuestionId)
.WillCascadeOnDelete(false);
}
}
public class Question
{
public long Id { get; set; }
public string Text { get; set; }
public virtual ICollection<Option> Options { get; set; }
public virtual ICollection<QuestionOption> DependencyOptions { get; set; }
}
public class Option
{
public long Id { get; set; }
public string Text { get; set; }
// [ForeignKey("QuestionId")]
public virtual Question Question { get; set; }
public long QuestionId { get; set; }
public virtual ICollection<QuestionOption> DependencyOptions { get; set; }
}
public class QuestionOption
{
public long OptionID { get; set; }
public Option Opiton { get; set; }
public long QuestionID { get; set; }
public Question Question { get; set; }
public int DependencyType { get; set; }
public string DependencyNote { get; set; }
public bool Active { get; set; }
public bool UseEtc { get; set; }
}
通过以下迁移...
CreateTable(
"dbo.Questions",
c => new
{
Id = c.Long(nullable: false, identity: true),
Text = c.String(maxLength: 4000),
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.Options",
c => new
{
Id = c.Long(nullable: false, identity: true),
Text = c.String(maxLength: 4000),
QuestionId = c.Long(nullable: false),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Questions", t => t.QuestionId)
.Index(t => t.QuestionId);
CreateTable(
"dbo.QuestionOptions",
c => new
{
OptionID = c.Long(nullable: false),
QuestionID = c.Long(nullable: false),
DependencyType = c.Int(nullable: false),
DependencyNote = c.String(maxLength: 4000),
Active = c.Boolean(nullable: false),
UseEtc = c.Boolean(nullable: false),
})
.PrimaryKey(t => new { t.OptionID, t.QuestionID })
.ForeignKey("dbo.Options", t => t.OptionID)
.ForeignKey("dbo.Questions", t => t.QuestionID)
.Index(t => t.OptionID)
.Index(t => t.QuestionID);
您定义了两个单独的关系(一个一对多和另一个 m-to-m),并排。
在QuestionOption
表中,您现在可以手动指定您需要为依赖项添加的所有内容(这就是您的 DependencyOption - 我只是认为这个命名可以更清楚地说明它)。所以你会有类似的东西Question(A) -> allows Option(B)
- 但考虑到你的逻辑,你可能需要添加更多。
看起来您需要在两者之间建立关系Question, Question, Option
- 所以 3 个索引等。鉴于上面的代码,如果需要,您可以通过一个简单的扩展来做到这一点。
modelBuilder.Entity<QuestionOption>()
.HasKey(i => new { i.OptionID, i.QuestionLeftID, i.QuestionRightID });
modelBuilder.Entity<QuestionOption>()
.HasRequired(i => i.Opiton)
.WithMany(u => u.DependencyOptions)
.HasForeignKey(i => i.OptionID)
.WillCascadeOnDelete(false);
modelBuilder.Entity<QuestionOption>()
.HasRequired(i => i.QuestionLeft)
.WithMany(u => u.DependencyOptionsLeft)
.HasForeignKey(i => i.QuestionLeftID)
.WillCascadeOnDelete(false);
modelBuilder.Entity<QuestionOption>()
.HasRequired(i => i.QuestionRight)
.WithMany(u => u.DependencyOptionsRight)
.HasForeignKey(i => i.QuestionRightID)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Option>()
.HasRequired(i => i.Question)
.WithMany(u => u.Options)
.HasForeignKey(i => i.QuestionId)
.WillCascadeOnDelete(false);
public class Question
{
public long Id { get; set; }
public string Text { get; set; }
public virtual ICollection<Option> Options { get; set; }
public virtual ICollection<QuestionOption> DependencyOptionsLeft { get; set; }
public virtual ICollection<QuestionOption> DependencyOptionsRight { get; set; }
}
public class QuestionOption
{
public long QuestionLeftID { get; set; }
public Question QuestionLeft { get; set; }
public long QuestionRightID { get; set; }
public Question QuestionRight { get; set; }
public long OptionID { get; set; }
public Option Opiton { get; set; }
public int DependencyType { get; set; }
public string DependencyNote { get; set; }
public bool Active { get; set; }
public bool AllowForbid { get; set; }
}
对于更复杂的场景(在流畅的代码中使用多对多和手动定义关系 - 我推荐) - 看看我刚才制作的这些详细示例 - 它具有您可能需要的大部分映射。
使用codefirst或fluent API与同一实体的多对多(连接表)关系?
联接表中的 Code First Fluent API 和导航属性
带有附加数据的 EF 代码优先多对多
...如果您需要任何快速指示 - 让我知道问题 - 以及更多细节