Хорошо, я действительно борюсь с тем, как обновить список внешних ключей в MVC2 / EF4.
У меня есть отношение один ко многим между объектом Template, у которого может быть много или нет объектов TemplateScenario.
По сути, у меня есть метод редактирования в контроллере, который пытается сделать это:
// POST: /Modes/Edit/1
[HttpPost]
public ActionResult Edit(int id, FormCollection formValues)
{
Template template = _templateRepository.GetTemplate(id);
TemplateCreateViewModel viewModel = new TemplateCreateViewModel();
viewModel.Template = template;
viewModel.TemplateScenarioList = template.TemplateScenarios.ToList();
//Update the model
UpdateModel(viewModel);
UpdateModel(viewModel.Template.TemplateScenarios, "TemplateScenarioList", new[] { "ScenarioID", "TemplateID" });
_templateRepository.Save();
return RedirectToAction("Edit", new { id = template.TemplateID });
}
Этот код успешно обновляет объект шаблона. Он также добавляет дочерние объекты 'templatescenario', НО только в том случае, если я впервые добавил 'templatescenarios' в этот конкретный шаблон. Если какие-либо объекты шаблонов сценария уже существуют для данного шаблона, и я пытаюсь обновить их на основе нового списка, я получаю эту ошибку:
"Операция не удалась: отношение не может быть изменено, потому что один или несколько
из свойств внешнего ключа не обнуляется. Когда изменение сделано в
отношение, для свойства внешнего ключа установлено нулевое значение. Если
внешний ключ не поддерживает нулевые значения, должны быть определены новые отношения,
свойству внешнего ключа должно быть присвоено другое ненулевое значение или
несвязанный объект должен быть удален. "
_templateRepository.Save (); это просто вызов метода entity.SaveChanges () EF4.
Я могу решить эту проблему грязным путем, передав список идентификаторов шаблонов сценариев моему классу репозитория с помощью специального метода update, который выглядит следующим образом:
public void Update(Template template, IList<int> templateScenarios)
{
//Delete Old Entries
foreach (TemplateScenario ts in entities.TemplateScenarios)
{
if (ts.TemplateID == template.TemplateID)
{
if (templateScenarios == null)
entities.TemplateScenarios.DeleteObject(ts);
else if (!templateScenarios.Where(tsl => tsl == ts.ScenarioID).Any())
entities.TemplateScenarios.DeleteObject(ts);
}
}
//Don't need to add anything if they are null.
if (templateScenarios == null)
return;
//Add New Entries
foreach (int ts in templateScenarios)
{
if (!entities.TemplateScenarios.Where(tsc => tsc.ScenarioID == ts && tsc.TemplateID == template.TemplateID).Any())
{
TemplateScenario tempScenToAdd = new TemplateScenario();
tempScenToAdd.ScenarioID = ts;
tempScenToAdd.TemplateID = template.TemplateID;
entities.TemplateScenarios.AddObject(tempScenToAdd);
}
}
}
Но это просто грязно, и я думаю, что я так близок с первым, более автоматическим методом. Я искал в интернете и нашел несколько похожих постов по stackoverflow, но мне трудно достичь этого «ага» момента.
Спасибо
Том.