Search code examples
c#entity-frameworkmany-to-manyentity-framework-migrationsasp.net-core-5.0

How to set name of index or foreign key explicitly on "half" many-to-many in migration for Entity Framework?


I have two classes like so.

public class Client { public Guid Id { get; set; } ... }
public class Meeting
{
  public Guid Id { get; set; }
  public Client[] Invitees { get; set; } = new Client[0];
  public Client[] Attendees { get; set; } = new Client[0];
}

The config in the contex is as follows.

private static void OnModelCreating(EntityTypeBuilder<Client> entity) { }

private static void OnModelCreating(EntityTypeBuilder<Meeting> entity)
{
    entity.HasMany(a => a.Invitees);
    entity.HasMany(a => a.Attendees);
}

I only need the reference to the clients from my meetings. The clients need not to know anything. The meetings need to reference the clients twice or less (volountary presence, optional invitation).

The migration on the above creates two tables, which I'm perfectly fine with. But it creates two indices as well, like this.

migrationBuilder.CreateIndex(
    name: "IX_Clients_MeetingId",
    table: "Clients",
    column: "MeetingId");

migrationBuilder.CreateIndex(
    name: "IX_Clients_MeetingId1",
    table: "Clients",
    column: "MeetingId1");

I'm not fine with that. First of all, I expected only one index to be created, as we're indexing the sme table's primary keys. Secondly, if I can't dogde that, I dislike the digit in IX_Clients_MeetingId1.

  1. What can I do (if anything) to only have a single index created?
  2. How can I specify the name of the index if I'm not using WithMany()?

I'm not providing any links as a proof of effort. Checking MSDN, SO and blogs resulted in a lot of hits on the full M2M relation, i.e. .HasMany(...).WithMany(...) and that's not what I'm heading for. I saw a suggestion to manually make the change in the migration file but tempering with those is begging for issues later. I'm not sure how to google-off the irrelevant results and I'm starting to fear that the "half" M2M I'm attempting is a bad idea (there's no in-between table created, for instance).


Solution

  • Well, it seems that EF is assuming you have 2 one2many relations. So one Client could only be invited to at most one meeting.

    As a quick resolution you can either

    1. add 2 join entities explicitly and configure the appropriate one2many relations. Then you have one table for Invitations and one for Attendance.
    2. add one many2many join entity that also tracks a link type (Client, Meeting, LinkType) so that "invited" and "attended" are link types
    3. Add 2 properties to Client to show EF that you mean this as a many2many relation:

    Like so:

    public class Client { 
      public Guid Id { get; set; }
      public ICollection<Meeting> InvitedTo { get; set; }
      public ICollection<Meeting> Attended { get; set; }
    }
    

    These should not show up in the clients table but as 2 separate tables. (Essentially solution 1 with implicit join entity)