错误地更新多对多连接表

时间:2013-04-07 04:50:54

标签: c# asp.net-mvc entity-framework ef-code-first many-to-many

我有一个ChangeRequest对象和一个具有多对多关系的BusinessArea对象。有一个连接表:ChangeRequestBusinessArea。

如果我使用BusinessAreaIDs 2,7,8和10创建并保存新的ChangeRequest,则连接表会更新。

e.g。

ChangeRequestID BusinessAreaID
1               2
1               7
1               8
1               10

但是当我随后编辑并使用BusinessAreaIDs 1,2,3,7和10保存相同的ChangeRequest时,我得到以下内容:

ChangeRequestID BusinessAreaID
1               2
1               7
1               8
1               10
1               11
1               12
1               13
1               14
1               15

以下是代码:

namespace MOC.Models
{
public class ChangeRequest
{
    public ChangeRequest()
    {
        BusinessAreas = new List<BusinessArea>();
    }

    public int ChangeRequestID { get; set; }
    public string ChangeRequestName { get; set; }

    public virtual ICollection<BusinessArea> BusinessAreas { get; set; }
}
}

namespace MOC.Models
{
public class BusinessArea
{
    public int BusinessAreaID { get; set; }
    public string BusinessAreaName { get; set; }

    public virtual ICollection<ChangeRequest> ChangeRequests { get; set; }
}
}

行动方法

[HttpPost]
public ActionResult Edit(int id, ChangeRequestViewModel ChangeRequestViewModel)
{
    if (ModelState.IsValid)
    {
        var changeRequest = new ChangeRequest
        {
            ChangeRequestID = id
        };

        AddOrUpdateBusinessAreas(changeRequest, ChangeRequestViewModel.BusinessAreas);
        db.Entry(changeRequest).State = EntityState.Modified;
        db.SaveChangeRequests();

        return RedirectToAction("Index");
        }
        return View(ChangeRequestViewModel);
    }

    private void AddOrUpdateBusinessAreas(ChangeRequest ChangeRequest, IEnumerable<AssignedBusinessAreaData> assignedBusinessAreas)
    {
        foreach (var assignedBusinessArea in assignedBusinessAreas)
        {
            if (assignedBusArea.Assigned) {
                var busarea = new BusArea { BusAreaID = assignedBusArea.BusAreaID };
                Change.BusAreas.Add(busarea);
            } else {
                var busarea = new BusArea { BusAreaID = assignedBusArea.BusAreaID };
                Change.BusAreas.Remove(busarea);
            }
        }
    }

1 个答案:

答案 0 :(得分:1)

您必须从数据库加载ChangeRequest,包括当前与其相关的BusinessArea,以便能够删除关系。

我假设ChangeRequestViewModel.AssignedBusinessAreaData包含所有可能包含标记Assigned的区域(如果该区域必须与ChangeRequest一致)。然后您的操作方法可能与此类似:

[HttpPost]
public ActionResult Edit(int id, ChangeRequestViewModel ChangeRequestViewModel)
{
    if (ModelState.IsValid)
    {
        var changeRequest = db.ChangeRequests
            .Include(c => c.BusinessAreas) // Important !
            .Single(c => c.ChangeRequestID == id);

        foreach (var assignedBusArea in ChangeRequestViewModel.BusinessAreas)
        {
            if (assignedBusArea.Assigned)
            {
                if (!changeRequest.BusinessAreas
                    .Any(b => b.BusinessAreaID == assignedBusArea.BusAreaID))
                {
                    var busArea = new BusinessArea
                    {
                        BusAreaID = assignedBusArea.BusAreaID
                    };
                    db.BusinessAreas.Attach(busArea);
                    // Attach is important to avoid duplication of the area
                    changeRequest.BusinessAreas.Add(busArea);
                }
                // else do nothing if the assigned area
                // already belongs to the changeRequest
            }
            else
            {
                var busArea = changeRequest.BusinessAreas.SingleOrDefault(
                    b => b.BusinessAreaID == assignedBusArea.BusAreaID);
                if (busArea != null)
                    changeRequest.BusinessAreas.Remove(busArea);
                // else do nothing if the unassigned area
                // does not belong to the changeRequest anyway
            }
        }
        db.SaveChanges();

        return RedirectToAction("Index");
    }            

    return View(ChangeRequestViewModel);
}