3

Does EF Core provide a way of naming the many-to-many relations mapping to database tables ?

In a code-first pattern, I have the following 2 Entities:

[Table("Prefix.Users")]
public class User
{
    public int ID { get; set; }
    public IEnumerable<Role> Roles { get; set; }
}


[Table("Prefix.Roles")]
public class Role
{
    public int ID { get; set; }
    public IEnumerable<User> Users { get; set; }
}

I've skipped the detailed Entity structure here. The ID properties in User & Role are keys (Database generated Identity)

User and Role entities share a many-to-many relationship.

EF Core generates a third table in Database with Table name UsersRoles

Is there a way I can add a prefix to the 3rd table name so it becomes Prefix.UsersRoles without manually adding a third Entity UserRoles that maps User and Role and giving it the desired name with Prefix

Naveen
  • 1,193
  • 4
  • 13
  • 17
  • Additionally to the post marked as duplicate, basically the same is contained in the current documentation [Join entity type configuration](https://learn.microsoft.com/en-us/ef/core/modeling/relationships?tabs=fluent-api%2Cfluent-api-simple-key%2Csimple-key#join-entity-type-configuration) – Ivan Stoev Aug 26 '21 at 19:13

1 Answers1

2

Use fluent API instead of using data annotations

Your model classes should be like this.

 public class User
 {
    public int Id { get; set; }
    public string Username { get; set; }
    public string Email { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Password { get; set; }

     public virtual ICollection<UserRole> UserRoles { get; set; }
}

public class Role
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    public virtual ICollection<UserRole> UserRoles { get; set; }
}

public class UserRole
{
    public int UserId { get; set; }
    public int RoleId { get; set; }

    public virtual User User { get; set; }
    public virtual Role Role { get; set; }

}

Your fluent api configuration classes like be this

public class UserConfiguration : IEntityTypeConfiguration<User>
{
    public void Configure(EntityTypeBuilder<User> builder)
    {
        builder.ToTable("User");

        builder.HasKey(x => x.Id);
    }
}
public class RoleConfiguration : IEntityTypeConfiguration<Role>
{
    public void Configure(EntityTypeBuilder<Role> builder)
    {
        builder.ToTable("Role");

        builder.HasKey(x => x.Id);
    }
}

public class UserRoleConfiguration : IEntityTypeConfiguration<UserRole>
{
    public void Configure(EntityTypeBuilder<UserRole> builder)
    {
        builder.ToTable("UserRole");

        builder.HasKey(x => new { x.UserId, x.RoleId });

        builder
            .HasOne<Role>(s => s.Role)
            .WithMany(r => r.UserRoles)
            .HasForeignKey(s => s.RoleId).OnDelete(DeleteBehavior.Restrict);

        builder
            .HasOne<User>(s => s.User)
            .WithMany(r => r.UserRoles)
            .HasForeignKey(s => s.UserId).OnDelete(DeleteBehavior.Restrict);

    }
}

Your DbContext class should be like this

public class MyDbContext : DbContext
{
    public EEGDbContext()
    {
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlServer(@"Server=xxxx;Database=DB;User Id=sa;Password=xxxxx;");
        }
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.ApplyConfiguration(new UserConfiguration());
        modelBuilder.ApplyConfiguration(new RoleConfiguration());
        modelBuilder.ApplyConfiguration(new UserRoleConfiguration());

        base.OnModelCreating(modelBuilder);
    }

    public DbSet<User> Users { get; set; }
    public DbSet<Role> Roles { get; set; }
    public DbSet<UserRole> UserRoles { get; set; }

}
  • 1
    Thanks for the elaborate response @Erandika. I was kind-of hoping if this third Entity `UserRole` creation can be skipped and EF Core takes care of it as it is doing right now _(my current setup)_ and we can still pick a **custom table name**. – Naveen Aug 26 '21 at 16:36
  • any chance you were able to figure this out without having to use 'UserRole' ? – OverMars Aug 03 '22 at 22:59
  • 1
    @OverMars I followed this - https://learn.microsoft.com/en-us/ef/core/modeling/relationships?tabs=fluent-api%2Cfluent-api-simple-key%2Csimple-key#join-entity-type-configuration – Naveen Mar 30 '23 at 11:43