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();
}
这个问题是由于并非实体类中的每个属性都是虚拟的。试试这个(对我有用):
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中的属性混合是一个好主意。