Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FK to the Same Table Code First Entity Framework

I am new to Code-First approach in Entity Framework. And I am a bit confused on how to do this:

I need a FK relationship to the same table, so I can have a Parent --> Child relationship between the elements.

This is the Model of the Table:

public class BucketGroup
{
   public int Id {get;set;} // This is the PK in the Table

   public string Name {get;set;}


   // Now this the FK, to this Same Table:
  public int? BucketGroupId {get;set;}

}

So I have made this item Nullable, if BucketGroupId is NULL then I know it is a parent Item.

I created a test project and worked with Database First, and the Model is something like this:

public partial class Testing
{
    public Testing()
    {
        this.Testing1 = new HashSet<Testing>();
    }

    public int Id { get; set; }
    public Nullable<int> ParentId { get; set; }

    public virtual ICollection<Testing> Testing1 { get; set; }
    public virtual Testing Testing2 { get; set; }
}

So If I add a similar Property to my Model will that make it an FK to the PK Id?

public class BucketGroup
{
  public int Id {get;set;} // This is the PK in the Table

  public string Name {get;set;}


  // Now this the FK, to this Same Table:
  public int? BucketGroupId {get;set;}

  public virtual ICollection<BucketGroup> BucketGroup1 { get; set; }

}

Is this correct?

like image 568
Dawood Awan Avatar asked Apr 08 '15 13:04

Dawood Awan


1 Answers

You have two options to do that:

  • Using Data Annotations:

    public class BucketGroup
    {
      public int Id {get;set;} 
    
      public string Name {get;set;}
    
      [ForeignKey("ParentBucketGroup")]
      public int? ParentBucketGroupId {get;set;}
    
      public virtual BucketGroup ParentBucketGroup {get;set;}
    
      public virtual ICollection<BucketGroup> Children { get; set; }
    }
    

    Or, using Fluent Api:

    public class BucketGroup
    {
      public int Id {get;set;} 
    
      public string Name {get;set;}
    
      public int? ParentBucketGroupId {get;set;}
    
      public virtual BucketGroup ParentBucketGroup {get;set;}
    
      public virtual ICollection<BucketGroup> Children { get; set; }
    }
    

    And, to configure the relationship, you could override the OnModelCreating method on your context:

    modelbuilder.Entity<BucketGroup>().HasOptional(b=>b.ParentBucketGroup )
                                      .WithMany(b=>b.Children )
                                      .HasForeignKey(b=>b.ParentBucketGroupId);
    

Update

If you want, you can work with an one-directional (also called unidirectional) relationship, but you need to keep one of them.

If you remove the Children nav property, then, you configuration would be like this:

 modelbuilder.Entity<BucketGroup>().HasOptional(b=>b.ParentBucketGroup)
                                   .WithMany()
                                   .HasForeignKey(b=>b.ParentBucketGroupId);

Or, if you remove the ParentBuketGroup nav. property, then you need to do this:

 modelbuilder.Entity<BucketGroup>().HasOptional()
                                   .WithMany(b=>b.Children)
                                   .HasForeignKey(b=>b.ParentBucketGroupId);
like image 68
octavioccl Avatar answered Nov 07 '22 08:11

octavioccl