Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework Core Many to Many change navigation property names

I have a table called "LogBookSystemUsers" and I want to setup many to many functionality in EF Core 5. I almost have it working but the problem is my ID columns are named SystemUserId and LogBookId but when EF does the join it tries to use SystemUserID and LogBookID. This is my current configuration code:

modelBuilder.Entity<SystemUser>()
            .HasMany(x => x.LogBooks)
            .WithMany(x => x.SystemUsers)
            .UsingEntity(x =>
            {
                x.ToTable("LogBookSystemUsers", "LogBooks");
            });

I tried this:

modelBuilder.Entity<SystemUser>()
            .HasMany(x => x.LogBooks)
            .WithMany(x => x.SystemUsers)
            .UsingEntity<Dictionary<string, object>>("LogBookSystemUsers",
                x => x.HasOne<LogBook>().WithMany().HasForeignKey("LogBookId"),
                x => x.HasOne<SystemUser>().WithMany().HasForeignKey("SystemUserId"),
                x => x.ToTable("LogBookSystemUsers", "LogBooks"));

But that just adds two new columns instead of setting the names of the current columns.

This is all database first. I don't want to have to use a class for the many to many table because I do this all over in my project and I don't want a bunch of useless classes floating around. Any ideas?

like image 767
GBreen12 Avatar asked Nov 27 '20 21:11

GBreen12


People also ask

How does Entity Framework handle many-to-many relationships in core?

Many-to-many relationships require a collection navigation property on both sides. They will be discovered by convention like other types of relationships. The way this relationship is implemented in the database is by a join table that contains foreign keys to both Post and Tag .

How do I use navigation properties in Entity Framework?

A navigation property is an optional property on an entity type that allows for navigation from one end of an association to the other end. Unlike other properties, navigation properties do not carry data. A navigation property definition includes the following: A name.

What is an Entity Framework relationship navigation property?

Navigation properties describe the relationship between two entity types. They allow us to navigate from one end of the relationship to the other end. A relationship in the Entity Framework always has two endpoints. Each endpoint, which participates in the relationship must return a navigation property describing the relationship.

How to ignore navigation property ‘icollection<item>’ in Entity Framework?

Unable to determine the relationship represented by navigation property ‘Cart.Items’ of type ‘ICollection<Item>’. Either manually configure the relationship, or ignore this property using the ‘ [NotMapped]’ attribute or by using ‘EntityTypeBuilder.Ignore’ in ‘OnModelCreating’.

How to create a many-to-many relationship in Entity Framework Core?

There are no default conventions available in Entity Framework Core which automatically configure a many-to-many relationship. You must configure it using Fluent API. In the Entity Framework 6.x or prior, EF API used to create the joining table for many-to-many relationships.

How are navigation properties configured in a relationship?

The most common pattern for relationships is to have navigation properties defined on both ends of the relationship and a foreign key property defined in the dependent entity class. If a pair of navigation properties is found between two types, then they will be configured as inverse navigation properties of the same relationship.


Video Answer


1 Answers

Interesting bug, consider posting it to EF Core GitHub issue tracker.

By idea what you have tried should do it

modelBuilder.Entity<SystemUser>()
    .HasMany(x => x.LogBooks)
    .WithMany(x => x.SystemUsers)
    .UsingEntity<Dictionary<string, object>>("LogBookSystemUsers",
        x => x.HasOne<LogBook>().WithMany().HasForeignKey("LogBookId"),
        x => x.HasOne<SystemUser>().WithMany().HasForeignKey("SystemUserId"),
        x => x.ToTable("LogBookSystemUsers", "LogBooks"));

And it works for any other FK property names except the {RelatedEntity}Id when related entity PK property is called ID.

As workaround until it gets fixed, define explicitly the desired join entity properties before configuring the relationship:


// add this
modelBuilder.SharedTypeEntity<Dictionary<string, object>>("LogBookSystemUsers", builder =>

{
    builder.Property<int>("LogBookId");
    builder.Property<int>("SystemUserId");
});
// same as the original
modelBuilder.Entity<SystemUser>()
    .HasMany(x => x.LogBooks)
    .WithMany(x => x.SystemUsers)
    .UsingEntity<Dictionary<string, object>>("LogBookSystemUsers",
        x => x.HasOne<LogBook>().WithMany().HasForeignKey("LogBookId"),
        x => x.HasOne<SystemUser>().WithMany().HasForeignKey("SystemUserId"),
        x => x.ToTable("LogBookSystemUsers", "LogBooks"));
like image 137
Ivan Stoev Avatar answered Oct 22 '22 13:10

Ivan Stoev