У меня есть таблица в моей базе данных со связью "один ко многим" к другой таблице, которая имеет отношения к третьей таблице:
ParentObject
ChildObject
AnotherObject
Объекты отображаются в Платформу Объекта и выставляются через класс доступа к данным.
Казалось, что ViewModels рекомендуют, когда данные, которые будут отображены значительно, отличаются от объекта области, таким образом, я создал ViewModel следующим образом:
public class ViewModel {
public IList ParentObjects { get; set; }
public ParentObject selectedObject { get; set; }
public IList ChildObjects { get; set; }
}
У меня есть представление, которое отображает список ParentObjects и при нажатии позволит ChildObject быть измененным сохраненный.
<% using (Html.BeginForm()) { %>
<% foreach (var parent in Model.ParentObjects) { %>
ObjectID [<%= Html.Encode(parent.ID)%>]
<%= Html.Encode(parent.Name)%>
<%= Html.Encode(parent.Description)%>
<% } %>
<% if (Model.ParentObject != null) { %>
Name:
<%= Html.TextBoxFor(model => model.ParentObject.Name) %>
<%= Html.ValidationMessageFor(model => model.ParentObject.Name, "*")%>
Description:
<%= Html.TextBoxFor(model => model.ParentObject.Description) %>
<%= Html.ValidationMessageFor(model => model.ParentObject.Description, "*")%>
Child Objects
<% for (int i = 0; i < Model.ParentObject.ChildObjects.Count(); i++) { %>
<%= Html.DisplayTextFor(sd => sd.ChildObjects[i].Name) %>
<%= Html.HiddenFor(sd => sd.ChildObjects[i].ID )%>
<%= Html.TextBoxFor( sd => sd.ChildObjects[i].Description) %>
<%= Html.ValidationMessageFor(sd => sd.ChildObjects[i].Description, "*") %>
<% }
}
} %>
Это все хорошо работает. Мой вопрос вокруг лучшего способа обновить объекты EF и сохранить изменения назад в базе данных. Я первоначально попробовал:
[HttpPost]
public ActionResult Edit(ViewModel viewModel) {
ParentObject parent = myRepository.GetParentObjectByID(viewModel.SelectedObject.ID);
if ((!ModelState.IsValid)
|| !TryUpdateModel(parent, "SelectedObject", new[] { "Name", "Description" })) {
|| !TryUpdateModel(parent.ChildObjects, "ChildObjects", new[] { "Name", "Description" })) {
//Code to handle failure and return the current model snipped
return View(viewModel);
}
myRepository.Save();
return RedirectToAction("Edit");
}
Когда я пытаюсь сохранить изменение в дочернем объекте, я получаю это исключение: Объекты в 'MyEntities. ChildObject' участвуют в отношениях 'FK_ChildObject_AnotherObject'. 0 связанных 'AnotherObject' были найдены. 1 'AnotherObject' ожидается.
Расследование на StackOverflow и общий поиск с помощью Google привели меня к этому сообщению в блоге, которое, кажется, описывает мою проблему: TryUpdateModel () правильно не обрабатывает вложенные наборы. По-видимому, (и ступающий через отладчик подтверждает это) он создает новый ChildObject вместо того, чтобы связаться с объектами EF от моего инстанцированного контекста.
Моя работа hacky вокруг - это:
if (viewModel.ChildObjects.Count > 0) {
foreach (ChildObject modelChildObject in viewModel.ChildObjects) {
ChildObject childToUpdate = ParentObject.ChildObject.Where(a => a.ID == modelChildObject.ID).First();
childToUpdate.Name = modelChildObject.Name;
}
}
Это, кажется, хорошо работает. Мой вопрос Вам хорошие люди: существует ли корректный способ сделать это? Я попробовал после предложения за то, что сделал пользовательский образцовый редактор связей на ссылку блога, которую я отправил выше, но это не работало (была проблема с отражением, код ожидал, что определенные свойства будут существовать), и я должен был получить что-то идущее как можно скорее.
PS - Я попробовал к очистке код для сокрытия определенной информации, поэтому остерегайтесь, я, возможно, полил из шланга что-то. Я главным образом просто хочу знать, решили ли другие люди эту проблему.
Кратко посмотрим на ошибку с упоминанием FK_ChildObject_AnotherObject ... вы уверены, что в вашей модели данных EF, касающейся AnotherObject, все правильно?
В вашем вопросе вы указываете только две таблицы, но эта ошибка указывает на то, что ChildObject участвует в отношении 1 к * с AnotherObject, и что ни одна из них не присутствует в сущности при сохранении, вызывающей ошибку.
Попробуйте удалить AnotherObject из ситуации, чтобы проверить любые предполагаемые проблемы между ParentObject и ChildObject, или попробуйте изменить отношение FK_ChildObject_AnotherObject с 0..1 на * на короткое время для тестирования.