asp.net-mvcentity-frameworkviewmodelobjectstatemanager

An object with the same key already exists in the ObjectStateManager error in controller


I have the following ActionResults in my controller (truncated for simplicity). When I post, I am getting the error: An object with the same key already exists in the ObjectStateManager. I think this is because I am loading an entity in the GET ActionResult:

var t = iEquipmentTaskRepository.GetSingle(taskID);

and then loading it again in the post and trying to edit/save it. I need to add a new Maintenance entity to the database and update a value in the (existing) EquipmentTask entity. How can I get a reference to the EquipmentTask already in the ObjectStateManager? Or, would I be better off adding the EquipmentTask entity as a property in my MaintenanceViewModel? I only want to update one property/column in the EquipmentTask entity

// GET
public ActionResult Create(int taskID = 0)
{
    if (taskID == 0)
    {
        return RedirectToAction("SelectEquipmentTask", "Maintenance");
    }
    else
    {
        var t = iEquipmentTaskRepository.GetSingle(taskID);

        var maintenanceViewModel = new MaintenanceViewModel
        {
            DueDate = t.MaintenanceDueDate
        };
        return View(maintenanceViewModel);
    }
}

// POST
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(MaintenanceViewModel maintenanceViewModel)
{
    if (maintenanceViewModel.DueDate != null)
        nextDueDate = maintenanceViewModel.DueDate.AddDays(7);

    Maintenance maintenance = new Maintenance();
    maintenance.RowId = maintenanceViewModel.RowId;

    // this appears to be my problem. I am loading the same EquipmentTask as the GET method does

    var t = iEquipmentTaskRepository.GetSingle(maintenanceViewModel.TaskId);
    EquipmentTask equipmentTask = new EquipmentTask();
    equipmentTask.TaskId = maintenanceViewModel.TaskId;
    equipmentTask.MaintenanceDueDate = nextDueDate;

    try
    {
        if (ModelState.IsValid)
        {
            iMaintenanceyRepository.Add(maintenance);
            iMaintenanceyRepository.Save();

            iEquipmentTaskRepository.Edit(equipmentTask);
            iEquipmentTaskRepository.Save();

            // redirect to the Details view
            return RedirectToAction("Details", "Maintenance", new { id = maintenance.RowId });
        }
    }
    catch (DataException)
    {
        //Log the error (add a variable name after DataException)
        ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
    }
    return View(maintenanceViewModel);
}

Solution

  • I figured out what was going on. I didn't need to create a new instance of EquipmentTask (Duh):

    var t = iEquipmentTaskRepository.GetSingle(maintenanceViewModel.TaskId);
    
    EquipmentTask equipmentTask = new EquipmentTask(); // <-- this line was not necessary
    
    equipmentTask.TaskId = maintenanceViewModel.TaskId;
    equipmentTask.MaintenanceDueDate = nextDueDate;
    

    I wasn't adding a new instance, just updating an existing one. Once I removed the line, it worked:

    var equipmentTask = iEquipmentTaskRepository.GetSingle(maintenanceViewModel.TaskId);
    equipmentTask.TaskId = maintenanceViewModel.TaskId;
    equipmentTask.MaintenanceDueDate = maintenanceViewModel.NextDueDate;