EF代码优先的多对多更新

本文关键字:更新 代码 EF | 更新日期: 2023-09-27 18:05:09

我有两个模型它们是相关的'多对多'

<<p> 医生模型/strong>
public class Doctor
{
    public int Id { get; set; }
    [Required]
    public string Fullname { get; set; }
    public virtual List<Speciality> SelectedSpecialities { get; set; }
    public virtual List<Speciality> AllSpecialities { get; set; }
    public virtual List<int> PostedSpecialities { get; set; }
    public Doctor()
    {
        SelectedSpecialities = new List<Speciality>();
        PostedSpecialities = new List<int>();
    }
}
<<p> 专业模型/strong>
public class Specialty
{
    public int Id { get; set; }
    [Required]
    public string Title { get; set; }
    public virtual List<Doctor> Doctors { get; set; }
}

我也有这个流畅的代码来创建多对多的关系。

modelBuilder.Entity<Speciality>().HasMany(x => x.Doctors).WithMany(x => x.SelectedSpecialities).Map(x =>
        {
            x.ToTable("DoctorsSpecialities");
            x.MapLeftKey("SpecialityId");
            x.MapRightKey("DoctorId");
        });

我可以添加"医生"很好,但是当我试图"更新"医生的专业时,看起来EF并没有删除以前的关系。

我的意思是,如果我有(1,2)和(1,3)想用(1,1)来更新它,它不会删除(1,2)和(1,3)行,我将在最后得到(1,1)(1,2)(1,3)

更新方法

 [HttpPost]
    public ActionResult Add(Doctor m)
    {
        if (ModelState.IsValid)
        {
            context.Entry(m).State = System.Data.Entity.EntityState.Modified;
            m.SelectedSpecialities.Clear();
            // the line below returns a List<Specialty> of selected pecialties
            m.SelectedSpecialities = context.Specialities.Where(x => m.PostedSpecialities.Contains(x.Id)).ToList();
            context.SaveChanges();
            return RedirectToAction("Index");
        }
        return View();
    }

EF代码优先的多对多更新

这个问题是由于并非实体类中的每个属性都是虚拟的。试试这个(对我有用):

public class Doctor
{
    public virtual int Id { get; set; }
    public virtual string Fullname { get; set; }
    public virtual ICollection<Specialty> SelectedSpecialities { get; set; }
    public virtual ICollection<Specialty> AllSpecialities { get; set; }
    public virtual ICollection<int> PostedSpecialities { get; set; }
}
public class Specialty
{
    public virtual int Id { get; set; }
    public virtual string Title { get; set; }
    public virtual ICollection<Doctor> Doctors { get; set; }
}
public ActionResult Add(Doctor m)
{
    if (ModelState.IsValid)
    {
        context.Entry(m).State = System.Data.Entity.EntityState.Modified;
        m.SelectedSpecialities.Clear();
        // the line below returns a List<Specialty> of selected pecialties
        foreach(var speciality in context.Specialties.Where(x => m.PostedSpecialities.Contains(x.Id)))
        {
            m.SelectedSpecialities.Add(speciality);
        }
        context.SaveChanges();
    }
    return View();
}

通过使实体类中的所有属性都是虚拟的,实体可能会被ef机制跟踪,它们会在没有你的情况下初始化正确的导航属性列表。通常允许使用List<>作为导航属性的类型,但我更喜欢使用那里的ICollection,因为类不应该依赖于其他类,而是依赖于接口。如果您使用PostedSpecialities只从视图中获取值,而不是将其存储在db中,那么我不认为将其与存储在db中的属性混合是一个好主意。