EF代码优先多对多更新

时间:2014-05-24 10:17:29

标签: c# entity-framework asp.net-mvc-4

我有两个与多对多相关的模型

医生型号

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>();
    }
}

专业模特

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");
        });

我可以添加`Doctor`就好了,但是当我尝试`更新'医生的专业时,看起来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();
    }

1 个答案:

答案 0 :(得分:0)

问题是由于实体类中的每个属性都不是虚拟的。试试这个(适合我):

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&lt;&gt;作为导航属性的类型,但我更喜欢使用ICollection,因为类不应该依赖于其他类,而是依赖于接口。如果你使用PostedSpecialities只从视图中获取值而不是将它存储在db中,那么我认为将它与存储在db中的属性混合起来并不是一个好主意。