错误地更新多对多连接表

时间:2022-10-05 11:34:18

I have a ChangeRequest object and a BusinessArea object with a many-to-many relationship. There is a join table: ChangeRequestBusinessArea.

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

If I create and save a new ChangeRequest with BusinessAreaIDs 2,7,8 and 10, the join table updates just fine.

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

e.g.

例如

ChangeRequestID BusinessAreaID
1               2
1               7
1               8
1               10

But when I then edit and save the same ChangeRequest with BusinessAreaIDs 1,2,3,7 and 10, I get the following:

但是,当我随后编辑并使用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

Here is the code:

这是代码:

Classes

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

Action Method

行动方法

[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 个解决方案

#1


1  

You must load the ChangeRequest from the database including the BusinessAreas that are currently related to it in order to be able to remove a relationship.

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

I am assuming that ChangeRequestViewModel.AssignedBusinessAreaData contains all possible areas with a flag Assigned if the area has to be aasigned to the ChangeRequest or not. Then your action method might look similar to this:

我假设ChangeRequestViewModel.AssignedBusinessAreaData包含带有标志的所有可能区域如果区域必须与ChangeRequest一起分配,则分配。然后你的action方法看起来可能类似于:

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

#1


1  

You must load the ChangeRequest from the database including the BusinessAreas that are currently related to it in order to be able to remove a relationship.

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

I am assuming that ChangeRequestViewModel.AssignedBusinessAreaData contains all possible areas with a flag Assigned if the area has to be aasigned to the ChangeRequest or not. Then your action method might look similar to this:

我假设ChangeRequestViewModel.AssignedBusinessAreaData包含带有标志的所有可能区域如果区域必须与ChangeRequest一起分配,则分配。然后你的action方法看起来可能类似于:

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