Search code examples
entity-frameworkef-code-firstrelationships

Creating relationships in CodeFirst EF which reference each other


I having some issues setting up the correct relationships that I require for a database.

In words... I want to have a Firm which can multiple (zero:many) Branch

On the Firm I want to be able specify a HeadOffice which will exist will exist in the Branch table (zero:one)

What I expected to see is the Firm table to have the following fields: Id, Name, HeadOfficeId and on the Branches I expect to see: Id, TradingAs, Name, Firm_Id

Instead I see:

Firm table to have the following fields: Id, Name, HeadOfficeId

Branches I expect to see: Id, TradingAs, Name, Firm_Id, Firm_Id1

The model classes are as shown

public class Firm
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Branch> FirmBranches { get; set; }

    public virtual LawFirmBranch HeadOffice { get; set; }
}

public class Branch
{
    public int Id { get; set; }
    public string TradingAs {get;set;}
    public string Name {get;set;}


    public Firm Firm { get; set; }

}

I understand that this causes a circular reference type issue and I am happy to have the Firm HeadOffice to initially to be Null until there are values in the FirmBranches property.

Is there some way that I can specify that the HeadOffice has the null or one type relationship


Solution

  • If you're wanting to explicitly do this in your model, you can do this via data annotations:

    public class Firm { public int Id { get; set; } public string Name { get; set; }

    public virtual ICollection<Branch> FirmBranches { get; set; }
    
    [ForeignKey("HeadOffice")]
    public int? FirmId {get;set;}
    
    public virtual LawFirmBranch HeadOffice { get; set; }
    

    }

    If you dont want this exposed in your code, you'll need to do this via fluent:

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Firm>()
                .HasOptional(f => f.HeadOffice)
                .WithOptionalDependent();
        }
    

    This creates:

    enter image description here

    If you want to change the name of the key, you'd add a mapping to the end of the fluent map:

            modelBuilder.Entity<Firm>()
                .HasOptional(f => f.HeadOffice)
                .WithOptionalDependent()
                .Map(m => m.MapKey("YourKeyName"));