Search code examples
entity-framework-coremany-to-many

Entity Framework Core - 3 tier relationship


I have to apply a set of relationships with a system that incorporates a messaging system.

I have the two of my domain object with one mapping object (for the many-to-many relationship):

public class User
{

    public User()
    {
        UserMails = new List<UserMail>();
    }

    public int Id { get; set; }
    public ICollection<UserMail> UserMails { get; set; }
}

public class Mail
{
    public Mail()
    {
        UserMails = new List<UserMail>();
    }

    public int Id { get; set; }
    public string Title { get; set; }
    public string Body { get; set; }
    public ICollection<UserMail> UserMails { get; set; }
}

public class UserMail
{
    public int Id { get; set; }

    public int FromUserId { get; set; }
    public User FromUser { get; set; }

    public int ToUserId { get; set; }
    public User ToUser { get; set; }

    public int MailId { get; set; }
    public Mail Mail { get; set; }
}

How would I configure this relationship using Fluent API such that there's a many to many relationship between User and Mail and Mail can have 2 foreign keys back to the UserFrom and UserTo?

Any help on this would be greatly appreciated.


Solution

  • If you are trying to model the relationship between a mail and its sender/recipient, then you don't need a many-to-many relation, or 2 foreign keys in your joining entity. Instead, you need 2 one-to-many relations like below -

    public class User
    {
        public int Id { get; set; }
        public string Name { get; set; }
    
        public ICollection<Mail> ReceivedMails { get; set; }
        public ICollection<Mail> SentMails { get; set; }
    }
    
    public class Mail
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string Body { get; set; }
    
        public int SenderId { get; set; }
        public User Sender { get; set; }
    
        public int RecipientId { get; set; }
        public User Recipient { get; set; }
    }
    

    and you can configure them as -

    protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.Entity<Mail>()
            .HasOne(p => p.Sender)
            .WithMany(p => p.SentMails)
            .HasForeignKey(p => p.SenderId)
            .OnDelete(DeleteBehavior.NoAction);
    
        builder.Entity<Mail>()
            .HasOne(p => p.Recipient)
            .WithMany(p => p.ReceivedMails)
            .HasForeignKey(p => p.RecipientId)
            .OnDelete(DeleteBehavior.NoAction);
    }