Define relationship in EF Core

ぐ巨炮叔叔 提交于 2021-02-08 12:10:23

问题


How do I define the relationships here with EF Core?

I have an Employee table which has multiple Jobs

public class Employee
{
    public int EmployeeId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public List<HourlyRate> DefaultRate { get; set; }
    public string Note { get; set; }
    public bool Active { get; set; }
    public DateTime DateHired { get; set; }
    public List<PhoneNumber> PhoneNumbers { get; set; }
    public List<Address> Addresses { get; set; }
    public List<Job> Jobs { get; set; }
    public bool Deleted { get; set; }
}

And the Job class has an Employee object to navigate back to the employee and the Job has multiple Directors which are also Employees

public class Job
{
    public int JobId { get; set; }
    public Employee Employee { get; set; }
    public JobType Type { get; set; }
    public Department Department { get; set; }
    public List<Employee> Directors { get; set; }
    public bool Active { get; set; }
    public decimal HourlyRate { get; set; }
    public string Note { get; set; }
    public bool Deduction { get; set; }
    public int? DeductionPercent { get; set; }
}

This is my DbContext:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Employee>()
                .HasMany(employee => employee.Jobs)
                .WithOne(i => i.Employee);
}

Initially the Job only had a single Director and everything was good but the requirement has changed to have multiple directors and ef removed the Director column from the Job table and added a JobId column to the Employee table but the problem is that if i add that director to a second job by job.Directors.Add(director) EF overrides the job id of the of the director and the director is being removed from the previous job

I am using EF Core 2.2


回答1:


if a Job has only 1 Employee but multiple Directors (also Employee)

add public int EmployeeId {get; set;} to your Job class and add this

modelBuilder
.Entity<Job>()
.HasMany(p => p.Directors)
.WithMany(p => p.Jobs));

also, change List<> to ICollection<>




回答2:


You should tell EF through fluent API that there's a 1-to-many relationship from Employee to Job. Otherwise, EF may get confused.

The many-to-many relationship needs a junction table and matching entity in the model which you'll also need to configure through fluent API. You'll define two 1-to-many relationships from Employee and Job to that new entity. EF core does not directly support such relationships before 5.0.

If you are targeting SQL, then you need to mark at least one of the relationships as OnDelete(CascadeBehavior.NoAction). Otherwise, your model will generate invalid table defintions which will raise errors at creation time.

Update:

The junction table would be defined something like this.

public class Employee
{
    // ... other stuff
    public List<EmployeeJob> EmployeeJobs { get; set; }
}

public class Job
{
    // ... other stuff
    public List<EmployeeJob> EmployeeJobs { get; set; }
}

public class EmployeeJob
{
    public int EmployeeId { get; set; }
    public int JobId { get; set; }
    public Employee Employee { get; set; }
    public Job Job { get; set; }
}

// goes in DbContext

modelBuilder.Entity<EmployeeJob>.HasKey(x => new { x.EmployeeId, x.JobId });



回答3:


Try to use this code. Since your employee can have one or many jobs I added the table EmployeeJob and many-to-many relations. I think you just need to add IsDirector flag to Employee or maybe better something like an EmployeeType:

public class Employee

    {
        public Employee()
    {
        EmployeeJobs = new HashSet<EmployeeJob>();
    }
    [Key]
   
   public int EmployeeId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    
    public string Note { get; set; }
    public bool Active { get; set; }
    public DateTime DateHired { get; set; }
    
    
    public bool Deleted { get; set; }
    [InverseProperty(nameof(EmployeeJob.Employee))]
    public virtual ICollection<EmployeeJob> EmployeeJobs { get; set; }
}


public class Job
{
    public Job()
    {
        EmployeeJobs = new HashSet<EmployeeJob>();
    }
    [Required]
    public int JobId { get; set; }

    public bool Active { get; set; }
    public decimal HourlyRate { get; set; }
    public string Note { get; set; }
    public bool Deduction { get; set; }
    public int? DeductionPercent { get; set; }
    
    [InverseProperty(nameof(EmployeeJob.Job))]
    public virtual ICollection<EmployeeJob> EmployeeJobs { get; set; }
}

public class EmployeeJob
{
    [Key]
    public int Id { get; set; }

    public int EmployeeId { get; set; }

    [ForeignKey(nameof(EmployeeId))]
    [InverseProperty(nameof(EmployeeJob.Employee.EmployeeJobs))]
    public virtual Employee Employee { get; set; }

    public int JobId { get; set; }

    [ForeignKey(nameof(JobId))]
    [InverseProperty(nameof(EmployeeJob.Employee.EmployeeJobs))]
    public virtual Job Job { get; set; }
}


public class EmployeeDbContext : DbContext
{
    public EmployeeDbContext()
    {
    }

    public EmployeeDbContext(DbContextOptions<EmployeeDbContext> options)
        : base(options)
    {
    }
    public DbSet<Employee> Employees { get; set; }
    public DbSet<Job> Jobs { get; set; }
    public DbSet<EmployeeJob> EmployeeJobs { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
optionsBuilder.UseSqlServer(@"Server=localhost;Database=Employee;Trusted_Connection=True;");
    }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<EmployeeJob>(entity =>
        {
            entity.HasOne(d => d.Employee)
                .WithMany(p => p.EmployeeJobs)
                .HasForeignKey(d => d.EmployeeId)
                .OnDelete(DeleteBehavior.ClientSetNull)
                .HasConstraintName("FK_EmployeeJob_Employee");

            entity.HasOne(d => d.Job)
                .WithMany(p => p.EmployeeJobs)
                .HasForeignKey(d => d.JobId)
                .OnDelete(DeleteBehavior.ClientSetNull)
                .HasConstraintName("FK_EmployeeJob_Job");
        });

    }


来源:https://stackoverflow.com/questions/65706128/define-relationship-in-ef-core

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!