简体   繁体   English

Code First - 自引用一对多关系

[英]Code First - Self-referencing one to many relation

I've found a lot of similar questions here, but none of them seems to help me with my problem.我在这里发现了很多类似的问题,但似乎没有一个能帮助我解决问题。 Fluent api & attributes didn't help.流利的 api 和属性没有帮助。 The database was created, but when adding an object to it, it crashed.数据库已创建,但在向其中添加对象时,它崩溃了。 I want to have a class that has a collection of itself.我想要一个包含自身集合的类。 Here's the code I have:这是我的代码:

[Table("UObjects")]
public class UObject
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Browsable(false)]
    public long ID { get; set; }
    public string Name { get; set; }
    [Browsable(false)]
    public long? ParentID { get; set; }

    public virtual UObject UParent { get; set; }
    [Browsable(false)]
    public virtual ICollection<UObject> UObjects { get; set; }
}


public class MyContext : DbContext
{
    public DbSet<UObject> UObjects { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // This fluent API didn't help
        //modelBuilder.Entity<UObject>()
        //        .HasOptional(u => u.UParent)
        //        .WithMany(u => u.UObjects)
        //        .HasForeignKey(u => u.ParentID);

        //modelBuilder.Entity<UObject>()
        //        .HasOptional(u => u.UParent)
        //        .WithMany(u => u.UObjects)
        //        .Map(c =>
        //        {
        //            c.MapKey("ParentID");
        //            c.ToTable("UObjects");
        //        });
    }
}

Records in database are like this:数据库中的记录是这样的:

ID | Name       | ParentID
------------------------------------
1  | First      | 0
2  | SubFirst   | 1
3  | SubSecond  | 1
4  | SubThird   | 2
5  | SubFourth  | 2

So how my object should look after loading the entities is next:那么接下来我的对象应该如何加载实体:

   - First
      - SubFirst
         - SubThird
         - SubFourth
      - SubSecond

But every object has an empty collection.但是每个对象都有一个空集合。 What should I do to make it work properly?我应该怎么做才能使其正常工作?

You only need to mention the self reference by correcting on field rather than on navigating property like this:您只需要通过更正字段而不是像这样导航属性来提及自我引用:

 [ForeignKey("UParent")]    // EF need for self reference
 public long? ParentID { get; set; }

And in constructor, initialize navigation properties like this:在构造函数中,像这样初始化导航属性:

  public UObject()       
    {
        // this is necessary otherwise EF will throw null object reference error. You could also put ?? operator check for a more interactive solution.  
        UObjects = new List<UObject>(); 
    }

And also need to override as you were doing but like this:并且还需要像你一样重写但是像这样:

   protected override void OnModelCreating(DbModelBuilder modelBuilder)     
    {   
        // folowwing is also necessary in case you're using identity model     
        base.OnModelCreating(modelBuilder);               
        modelBuilder.Entity<UObjects>()       
            .HasOptional<UObjects>(u => u.UParent) // EF'll load Parent if any     
            .WithMany(u => u.UObjects);        // load all childs if any 
    }

An entity class almost identical to yours works in EF Core.在 EF Core 中可以使用与您的实体类几乎相同的实体类。 I renamed your property ParentID to UParentID and added constructors.我将您的属性ParentID重命名为UParentID并添加了构造函数。

[Table("UObjects")]
public class UObject
{
  protected UObject()
  {
    UObjects = new List<UObject>();
  }

  public UObject(UObject parent, string name)
    : this()
  {
    Name = name;
    UParent = parent;
    UParent?.UObjects.Add(this);
  }

  [Key]
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  public long ID { get; set; }
  public string Name { get; set; }
  public long? UParentID { get; set; }

  public virtual UObject UParent { get; set; }
  public virtual ICollection<UObject> UObjects { get; set; }
}

In ApplicationDBContext I only have this:ApplicationDBContext我只有这个:

protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);
    builder.Entity<UObject>();
}

Usage (see how the properties of the root object are filled with correct values):用法(查看root对象的属性如何填充正确的值): 预加载

Note: I didn't bother about deletion in this code.注意:我没有在意这段代码中的删除。 If you need it, things will probably get more complicated.如果你需要它,事情可能会变得更复杂。

  1. Decorate your UParent Property with ForeignKey Attribute and?用 ForeignKey 属性装饰你的 UParent 属性? since it can be nullable因为它可以为空

[ForeignKey("ParentID")] public virtual UObject? UParent { get; set; }

  1. In database: Set ParentId value to 'NULL' if there is no parent.在数据库中:如果没有父级,则将 ParentId 值设置为“NULL”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 两种自我参照的一对多关系 - Two self-referencing one to many relations 在 Entity Framework Core 中自引用多对多关系 - Self-referencing many to many relation in Entity Framework Core ASP.NET MVC 5实体框架6自引用一对多关系 - ASP.NET MVC 5 Entity Framework 6 Self-Referencing One-to-Many Relation Entity Framework Core 6 中的自引用零或一对多 (0-1 -&gt; N) 关系 - Self-referencing zero or one to many (0-1 -> N) relation in Entity Framework Core 6 实体框架代码优先使用错误ID的多对多自引用多属性 - Entity Framework Code First Self-Referencing Many-to-Many with additional properties using wrong Id 自引用多对多递归关系代码优先实体框架 - Self-referencing many-to-many recursive relationship code first Entity Framework EntityFramework Code首先自引用一对一(1:1)关系映射 - 无法确定主要结束 - EntityFramework Code First self-referencing one to one (1:1) relationship mapping - Unable to determine the principal end EF6代码优先-自引用配置导航属性 - EF6 Code First - Self-referencing configure navigation properties EF代码优先自引用复合密钥 - EF Code First Self-Referencing Composite Key 实体框架5代码优先自我引用关系 - Entity Framework 5 Code First Self-Referencing Relationship
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM