Home > OS >  How to create a 3 ways relationship in EF core 5
How to create a 3 ways relationship in EF core 5

Time:09-25

I'm using EntityFramework 5, and I have a model in which I have a many-to-many-to-many relationship. Here's my model :

public class User
{
    public int UserId { get; set; }
    public string UserName { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public string Email { get; set; }
    public UserStatus Status { get; set; } // Manager or user
    
    public ICollection<Contract> Contracts { get; set; }
}


public class Enterprise
{
    public int EnterpriseId{ get; set; }
    public string SIRET { get; set; }
    public string AdministrativeName { get; set; }
    public string PublicName { get; set; }
    public string Adress { get; set; }
    public string ZipCode { get; set; }
    public string City { get; set; }
    public string ContactEmail { set; get; }
    public string ContactName { get; set; }
    public string ContactPhoneNumber { get; set; }

    public ICollection<Contract> Contracts { get; set; }
}


public class Contract
{
    public int ContractId { get; set; }
    public int ConsultantId { get; set; }
    public User Consultant { get; set; }
    public int ManagerId { get; set; }
    public User Manager { get; set; }
    public int CustomerId { get; set; }
    public Enterprise Customer { get; set; }
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
}

protected override void OnModelCreating( ModelBuilder modelBuilder )
{
       modelBuilder.Entity<Contract>()
           .HasOne( c => c.Consultant )
           .WithMany( u => u.Contracts );

       /*modelBuilder.Entity<Contract>()
            .HasOne( c => c.Manager )
            .WithMany( m => m.Contracts );*/

       modelBuilder.Entity<Contract>()
            .HasOne( c => c.Customer )
            .WithMany( e => e.Contracts );

}

I have an employe who sign a contract with a customer. Each contract is supervised by a manager. Since a User can either be a manager or an employe, we have 2 links toward the user table, but one is toward an employe, one is toward a manager.

So far, it doesn't seem too complex, and the "Add-migration" script runs well. But, when I try to run the UpdateDatabase, I have this output :

Introducing FOREIGN KEY constraint 'FK_Contract_User_ManagerId' on table 'Contract' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.Could not create constraint or index. See previous errors.

I tried to fix it using the error tip, but it has no effects. Is there a way to link 3 entities in EF Core, or do I have to use a different model ?

Thanks

[Edit] I updated the code I posted

CodePudding user response:

Assuming that each contract has a manager and a consultant, add navigaion properties to user

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

    public UserStatus Status { get; set; } // Manager or user

    public ICollection<Contract> UserContracts { get; set; }
    public ICollection<Contract> ManagerContracts { get; set; }
}

if a contract can have 1 manager but several consultants, or several managers too, you will need one more table ContractConsultant. In this case your User will be like this

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

    public UserStatus Status { get; set; } // Manager or user

    public ICollection<ConsultanContract> UserContracts { get; set; }
    public ICollection<Contract> ManagerContracts { get; set; }
}

and you will have to remove from Contract

 public int ConsultantId { get; set; }
    public User Consultant { get; set; }

CodePudding user response:

That works, but I had to add some configuration in the OnModelCreating

protected override void OnModelCreating( ModelBuilder modelBuilder )
{
    modelBuilder.Entity<Contract>()
        .HasOne( c => c.Consultant )
        .WithMany( u => u.DevelopperContracts )
        .OnDelete(DeleteBehavior.NoAction);

    modelBuilder.Entity<Contract>()
        .HasOne( c => c.Manager )
        .WithMany( m => m.ManagerContracts )
        .OnDelete( DeleteBehavior.NoAction );

    modelBuilder.Entity<Contract>()
        .HasOne( c => c.Customer )
        .WithMany( e => e.Contracts )
        .OnDelete( DeleteBehavior.NoAction );
}
  • Related