2012-10-20 59 views
6

我在这里发现了很多类似的问题,但他们都没有帮我解决我的问题。流利的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 

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

+0

检查此问题http://stackoverflow.com/questions/10421351/many-to-many-relationship-between-entities-of-same-type-in​​-mvc3/10422172#10422172 – Shyju

+0

已经尝试过。它创建了数据库,但是当添加新对象并调用SaveChanges() – GaaRa

+5

“*它崩溃*”时,它崩溃并不是一个很好的问题描述。 1)确切的例外是什么? 2)当你使用空集合加载实体时,你运行了什么查询? 3)为什么在第一个数据库行中有'ParentID'为'0'?它违反了参考约束(没有'ID' 0的行)。或者你的意思是'NULL'? – Slauma

回答

-3
  1. 用ForeignKey属性装饰你的UParent属性?因为它可以是可空

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

  • 在数据库:设置的ParentId值 'NULL' 如果没有父节点。
  • +2

    The?是无效的,因为UObject是一个类,而不是一个值类型。 –

    5

    你只需要通过现场纠正,而不是像这样的导航属性所提到的自我参考:

    [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 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 
        } 
    
    +0

    我对类别和子类别以及许多需要自引用的地方实现相同的行为。如果还没有得到想要的结果,请随时免费 –

    +0

    在构造函数中初始化集合不是必须的。 EF将在空值时创建它。 –

    1

    实体类与您的EF Core几乎完全相同。我将您的房产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; } 
    } 
    

    ApplicationDBContext我只有这个:

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

    用法(怎么看root对象的属性都充满了正确的值): Eager loading

    注:我没有在此代码中打扰删除。如果你需要它,事情可能会变得更加复杂。