8

我在这里发现了很多类似的问题,但似乎没有一个可以帮助我解决我的问题。流利的 api 和属性没有帮助。数据库已创建,但在向其中添加对象时,它崩溃了。我想要一个有自己集合的类。这是我的代码:

[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");
        //        });
    }
}

数据库中的记录是这样的:

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

那么我的对象在加载实体后应该如何看待接下来是:

   - First
      - SubFirst
         - SubThird
         - SubFourth
      - SubSecond

但是每个对象都有一个空集合。我应该怎么做才能使其正常工作?

4

3 回答 3

7

您只需要通过更正字段而不是像这样的导航属性来提及自我引用:

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

在构造函数中,像这样初始化导航属性:

  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>(); 
    }

并且还需要像您所做的那样覆盖,但像这样:

   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 
    }
于 2017-01-10T10:36:49.617 回答
2

与您的几乎相同的实体类在 EF Core 中工作。我将您的属性重命名ParentIDUParentID并添加了构造函数。

[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; }
}

ApplicationDBContext我只有这个:

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

用法(查看root对象的属性如何填充正确的值): 渴望加载

注意:我没有为删除此代码而烦恼。如果你需要它,事情可能会变得更复杂。

于 2017-01-12T00:31:13.107 回答
-3
  1. 用 ForeignKey 属性和 ? 装饰您的 UParent 属性 因为它可以为空

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

  1. 在数据库中:如果没有父级,则将 ParentId 值设置为“NULL”。
于 2017-01-09T13:48:22.720 回答