Search code examples
c#entity-frameworkentity-framework-6many-to-many

EF Many-to-many relationship with same entities


I'm currently facing as problem where I have single entity (Artist) which can be either a 'headliner' or 'support act' for a given Event in a many-to-many relationship.

An extremly simplified version of these tables:

 +----------------+     +----------------+
 | Artist         |     | Event          |
 +----------------+     +----------------+
 | ArtistId       |     | EventId        |
 | ExternalId     |     | Name           |
 | Name           |     |                |
 +----------------+     +----------------+

As an intermediate solution I have introduced two additional entities to meet these requirements.

 +----------------+     +----------------+
 | Headliner      |     | SupportAct     |
 +----------------+     +----------------+
 | ArtistId       |     | ArtistId       |
 | EventId        |     | EventId        |
 +----------------+     +----------------+

And introduced the following code in the Event entity

    private ICollection<Headliner> _headliners;

    public virtual ICollection<Headliner> Headliners
    {
        get { return _headliners ?? (_headliners = new Collection<Headliner>()); }
        protected set { _headliners = value; }
    }

    private ICollection<SupportAct> _supportActs;

    public virtual ICollection<SupportAct> SupportActs
    {
        get { return _supportActs ?? (_supportActs = new Collection<SupportAct>()); }
        protected set { _supportActs = value; }
    }

What I'm trying to accomplish is a more streamlined solution which would look something like you'll find below.

And where the code would be reduced to something like you'll find below. But this is not allowed....

    private ICollection<Artist> _headliners;

    public virtual ICollection<Artist> Headliners
    {
        get { return _headliners ?? (_headliners = new Collection<Artist>()); }
        protected set { _headliners = value; }
    }

    private ICollection<Artist> _supportActs;

    public virtual ICollection<Artist> SupportActs
    {
        get { return _supportActs ?? (_supportActs = new Collection<Artist>()); }
        protected set { _supportActs = value; }
    }

Is something like described above feasible as it would give me direct access to the Artist entities?


Solution

  • If I understand correctly, you want to switch to many-to-many association with implicit junction table. And you need two such associations between the same entities.

    Well, you can configure two (or as many as you wish) associations between the same entities the same way you define one association - using fluent configuration. Simply remove the Headliner and SupportAct entities and use the following:

    modelBuilder.Entity<Event>()
        .HasMany(e => e.Headliners)
        .WithMany()
        .Map(a => a.ToTable("Headliner")
            .MapLeftKey("EventId")
            .MapRightKey("ArtistId"));
    
    modelBuilder.Entity<Event>()
        .HasMany(e => e.SupportActs)
        .WithMany()
        .Map(a => a.ToTable("SupportAct")
            .MapLeftKey("EventId")
            .MapRightKey("ArtistId"));