我有一个这样的课程:
[Table("Tree")]
public class Tree
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int TreeId { get; set; }
public int? TreeOneId { get; set; }
[ForeignKey("TreeOneId")]
public virtual Tree TreeOne { get; set; }
public int? TreeTwoId { get; set; }
[ForeignKey("TreeTwoId")]
public virtual Tree TreeTwo { get; set; }
}
当我从这个类定义创建数据库时,我收到错误:
无法确定类型“树”和“树”之间关联的主要结束。必须使用关系流畅API或数据注释显式配置此关联的主要结尾。
如果我删除其中一个属性,并创建一个类定义:
[Table("Tree")]
public class Tree
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int TreeId { get; set; }
public int? TreeOneId { get; set; }
[ForeignKey("TreeOneId")]
public virtual Tree TreeOne { get; set; }
//public int? TreeTwoId { get; set; }
//[ForeignKey("TreeTwoId")]
//public virtual Tree TreeTwo { get; set; }
}
它确实创建了正确的表格。我怎么能得到这个错误?我已经尝试指定列顺序,添加一个唯一索引。我可以通过使用List TreeOne解决这个问题,它将创建相应的链接表,但我宁愿不必使用该解决方案。
答案 0 :(得分:2)
这里的基本问题是,SQL不允许您精确定义二叉树。
在你的方法中,树项有可能有多个父项,因为没有什么能阻止LeftId和RightId指向同一个引用或者让另一个树项指向同一个子树。
我们需要为左/右导航属性定义一个终点。这是解决方案的关键:为左/右子项定义单独的反向导航属性,并考虑是否有多个父项。
考虑到这一点,让我们为实体框架设置模型。请注意,我将Tree
替换为TreeItem
,因为每个树节点有一个条目,并使用Left
,Right
代替您的属性名称,而不是懒惰。
public class TreeItem
{
public int Id { get; set; }
public int? LeftId { get; set; }
public int? RightId { get; set; }
[ForeignKey("LeftId")]
[InverseProperty("Parent1")]
public virtual TreeItem Left { get; set; }
[ForeignKey("RightId")]
[InverseProperty("Parent2")]
public virtual TreeItem Right { get; set; }
[InverseProperty("Left")]
public virtual ICollection<TreeItem> Parent1 { get; set; }
[InverseProperty("Right")]
public virtual ICollection<TreeItem> Parent2 { get; set; }
}
另请注意:我仅在EF6中测试过,因此无法保证使用EF5