Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF Core - Many to many relationship on a class

User-Friend relationship

I find an answer

Entity Framework Core: many-to-many relationship with same entity and try like this.

Entitys:

public class User
{
    public int UserId { get; set; }

    public virtual ICollection<Friend> Friends { get; set; }
}

public class Friend
{
    public int MainUserId { get; set; }

    public User ManUser { get; set; }

    public int FriendUserId { get; set; }

    public User FriendUser { get; set; }
}

The fluent API:

modelBuilder.Entity<Friend>()
    .HasKey(f => new { f.MainUserId, f.FriendUserId });

modelBuilder.Entity<Friend>()
    .HasOne(f => f.ManUser)
    .WithMany(mu => mu.Friends)
    .HasForeignKey(f => f.MainUserId);

modelBuilder.Entity<Friend>()
    .HasOne(f => f.FriendUser)
    .WithMany(mu => mu.Friends)
    .HasForeignKey(f => f.FriendUserId);

When I Add-Migration, the error message is

Cannot create a relationship between 'User.Friends' and 'Friend.FriendUser', because there already is a relationship between 'User.Friends' and 'Friend.ManUser'. Navigation properties can only participate in a single relationship.

What should I do? Or I should create an Entity FriendEntity:User?

like image 993
Lin Baby Avatar asked Mar 12 '17 08:03

Lin Baby


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 you insert a many-to-many relationship?

When you need to establish a many-to-many relationship between two or more tables, the simplest way is to use a Junction Table. A Junction table in a database, also referred to as a Bridge table or Associative Table, bridges the tables together by referencing the primary keys of each data table.

Is EF core faster than EF6?

Entity Framework (EF) Core, Microsoft's object-to-database mapper library for . NET Framework, brings performance improvements for data updates in version 7, Microsoft claims. The performance of SaveChanges method in EF7 is up to 74% faster than in EF6, in some scenarios.


2 Answers

The problem is that you can't have one collection to support both one-to-many associations. Friend has two foreign keys that both need an inverse end in the entity they refer to. So add another collection as inverse end of MainUser:

public class User
{
    public int UserId { get; set; }
    public virtual ICollection<Friend> MainUserFriends { get; set; }
    public virtual ICollection<Friend> Friends { get; set; }
}

And the mapping:

modelBuilder.Entity<Friend>()
    .HasKey(f => new { f.MainUserId, f.FriendUserId });

modelBuilder.Entity<Friend>()
    .HasOne(f => f.MainUser)
    .WithMany(mu => mu.MainUserFriends)
    .HasForeignKey(f => f.MainUserId).OnDelete(DeleteBehavior.Restrict);

modelBuilder.Entity<Friend>()
    .HasOne(f => f.FriendUser)
    .WithMany(mu => mu.Friends)
    .HasForeignKey(f => f.FriendUserId);

One (or both) of the relationships should be without cascading delete to prevent multiple cascade paths.

like image 199
Gert Arnold Avatar answered Oct 06 '22 01:10

Gert Arnold


It's not mandatory the second collection. You only need to left de .WithMany() empty like this:

modelBuilder.Entity<Friend>()
    .HasOne(f => f.MainUser)
    .WithMany()
    .HasForeignKey(f => f.MainUserId);

modelBuilder.Entity<Friend>()
    .HasOne(f => f.FriendUser)
    .WithMany()
    .HasForeignKey(f => f.FriendUserId);

look at this : https://github.com/aspnet/EntityFramework/issues/6052

like image 28
Alejo Ferrand Avatar answered Oct 06 '22 03:10

Alejo Ferrand