如何为自引用对象类型建模

本文关键字:类型 建模 对象 自引用 | 更新日期: 2023-09-27 18:01:44

假设我有一个类Box:

public class Box
{
    [Required]
    [Key]
    int BoxId { get; set; }
    string BoxName { get; set; }
}

我希望能够添加盒子到其他盒子-一个盒子可以有许多盒子或属于一个盒子,但它不需要。

我试图在我的项目中像这样建模:

public class Box
{
    [Required]
    [Key, ForeignKey("ParentBox")]
    int BoxId { get; set; }
    string BoxName { get; set; }
    int ParentBoxId { get; set; }
    Box ParentBox { get; set; }
    List<Box> Boxes {get; set;}
}

然而,在这个问题中我得到了以下错误:

无法确定的主端"App.Core。Set_ParentSet"关系。多个添加的实体可以有相同的主键。

删除ForeignKey属性可以让我构建数据库,但是级联删除不起作用。

我不想为ChildBox或ParentBox创建一个不同的类,因为一个box是否属于/有box在我的应用程序中会一直改变。

在EF中建模的正确方法是什么?

如何为自引用对象类型建模

试一下

public class Box
{
    [Required]
    [Key]
    public int BoxId { get; set; }
    public string BoxName { get; set; }
    public int ParentBoxId { get; set; }
    // The foreign key for the Box that points at ParentBox.BoxId  (the [Key])
    [ForeignKey("ParentBoxId")]
    public Box ParentBox { get; set; }
    // The foreign key for the Boxes that point at this.BoxId (the [Key])
    [ForeignKey("ParentBoxId")]
    public virtual ICollection<Box> Boxes {get; set;}
}

一个Fluent API版本。你可以用Tyriar建议的annotation来做。我个人不喜欢我的POCOs里有Db垃圾。所以这里有一个替代方案…

modelBuilder.Entity<Box>().
  HasOptional(e => e.ParentBox).
  WithMany().
  HasForeignKey(p => p.ParentBoxID);

BoxID有问题。它同时是主键和外键?使用示例请参见http://msdn.microsoft.com/en-us/data/gg193958

InverseProperty可以用来代替外键。这减少了冗余的数量。

   [Table("Box")]
public class Box
{
    [Required]
    [Key]
    [Column("BoxId")]
    public virtual int BoxId { get; set; }
    [Column("Name")]
    public virtual string Name { get; set; }
    [Column("ParentBoxID")]
    public virtual int? MyParentBoxId { get; set; }
    [ForeignKey("MyParentBoxId")]
    public virtual Box Parent { get; set; }
    [InverseProperty("Parent")]
    public virtual ICollection<Box> Boxes { get; set; }
}