Search code examples
c#entity-framework-4.1ef-code-firstfluent-interface

Entity Framework Code First - One-to-Many with a join/link table


Is it possible to create a One-to-Many relationship with Code First that uses a link/join table between them?

public class Foo {
    public int FooId { get; set; }
    // ...

    public int? BarId { get; set; }
    public virtual Bar Bar { get; set; }
}

public class Bar { 
    public int BarId { get; set; }
    // ...

    public virtual ICollection<Foo> Foos { get; set; }
}

I want this to map as follows:

TABLE Foo
    FooId INT PRIMARY KEY
    ...

TABLE Bar
    BarId INT PRIMARY KEY

TABLE FooBar
    FooId INT PRIMARY KEY / FOREIGN KEY
    BarId INT FOREIGN KEY

With this, I would have the ability to make sure Foo only has one Bar, but that Bar could be re-used by many different Foos.

Is this possible with Entity Framework? I would prefer to not have to put the key in Foo itself because I don't want a nullable foreign key. If it is possible please provide an example using the Fluent API and not the data annotations.


Solution

  • You can use Entity splitting to achieve this

    public class Foo
    {
        public int FooId { get; set; }
    
        public string Name { get; set; }
    
        public int BarId { get; set; }
    
        public virtual Bar Bar { get; set; }
    }
    

    Then in your custom DbContext class

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Foo>().HasKey(f => f.FooId);
            modelBuilder.Entity<Foo>()
                .Map(m =>
                         {
                             m.Properties(b => new {b.Name});
                             m.ToTable("Foo");
                         })
                .Map(m =>
                         {
                             m.Properties(b => new {b.BarId});
                             m.ToTable("FooBar");
                         });
    
            modelBuilder.Entity<Foo>().HasRequired(f => f.Bar)
                .WithMany(b => b.Foos)
                .HasForeignKey(f => f.BarId);
    
            modelBuilder.Entity<Bar>().HasKey(b => b.BarId);
            modelBuilder.Entity<Bar>().ToTable("Bar");
        }
    

    The BarId column will be created as a not null column in FooBar table. You can check out Code First in the ADO.NET Entity Framework 4.1 for more details