Entity Framework Core: many-to-many relationships with the same object

I am trying to match many-to-many relationships with the same object. The User object has an IList<User> data field for Contacts , in which data about users' contacts / friends is stored:

 public class User : DomainModel { public virtual IList<User> Contacts { get; protected set; } //irrelevant code omitted } 

When I try to use the free API to map many relationships, this causes some problems. Apparently, when I use HasMany() in the user.Contacts property, it does not have a WithMany() method to call the following. Intellisense from Visual Studio only shows WithOne() , but not WithMany() .

 modelBuilder.Entity<User>().HasMany(u => u.Contacts).WithMany() // gives compile time error: CS1061 'CollectionNavigationBuilder<User, User>' does not contain a definition for 'WithMany' and no extension method 'WithMany' accepting a first argument of type 

So why is this happening? Is there something I did wrong to match this many-to-many relationship?

+8
c # entity-framework entity-framework-core
source share
2 answers

So why is this happening? Did I do something wrong to inflict a many-to-many relationship?

No, you did nothing wrong. It is simply not supported . Current status is here .

Many-to-many relationships without an entity class to represent a join table are not yet supported. However, you can imagine many-to-many relationships, including an entity class to join a table and display two separate one-to-many relationships.

With EF-Core, you must create an object for the mapping table. For example, UserContacts . Full example in docs as indicated in the comments. I have not actually tested the code below, but it should look something like this:

 public class UserContacts { public int UserId { get; set; } public virtual User User { get; set; } public int ContactId { get; set; } // In lack of better name. public virtual User Contact { get; set; } } public class User : DomainModel { public List<UserContacts> Contacts { get; set; } } 

And your modelBuilder .

  modelBuilder.Entity<UserContacts>() .HasOne(pt => pt.Contact) .WithMany(p => p.Contacts) .HasForeignKey(pt => pt.ContactId); modelBuilder.Entity<UserContacts>() .HasOne(pt => pt.User) .WithMany(t => t.Contacts) .HasForeignKey(pt => pt.UserId); 
+19
source share

Maybe I was late, but @smokesnes, the answer will not work for many with many relationships for the same object until version 2.1 of the infrastructure platform. But his answer will work well for many with many relationships with another entity.

Here's a solution for many-to-many relationships for the same entity (before EF Core 2.1)

 public class UserContacts { public int UserId { get; set; } public virtual User User { get; set; } public int ContactId { get; set; } public virtual User Contact { get; set; } } public class User : DomainModel { public List<UserContacts> UserContacts { get; set; } public List<UserContacts> ContactUsers { get; set; } } 

Then in the model constructor:

 protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<Relationship>().HasKey(r => new {r.UserId, r.ContactId}); modelBuilder.Entity<UserContacts>() .HasOne(pt => pt.User) .WithMany(p => p.UserContacts) .HasForeignKey(pt => pt.UserId).OnDelete(DeleteBehavior.Restrict);; modelBuilder.Entity<UserContacts>() .HasOne(pt => pt.Contact) .WithMany(t => t.ContactUsers) .HasForeignKey(pt => pt.ContactId).OnDelete(DeleteBehavior.Restrict);; } 
0
source share

All Articles