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. 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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With