MVC2 RTM - модель связывания сложных объектов с использованием Entity Framework - PullRequest
1 голос
/ 26 августа 2010

Я новичок в MVC и действительно борюсь с тем, что, как мне кажется, должно быть очень распространенным сценарием. Я использую MVC2 RTM и Entity Framework для своих объектов модели.

Что у меня работает:

Представление редактирования для родительского объекта, которое содержит коллекцию дочерних объектов. Форма отображает все редактируемые поля для родительского элемента, выполняет итерацию и отображает все редактируемые поля для всех связанных дочерних объектов (в том же виде). Я могу успешно обработать действие редактирования в моем контроллере, но сталкиваюсь с проблемами при попытке привязать значения в коллекции форм к объектам модели EF.

Проблема:

В моей функции контроллера, когда я вызываю TryUpdateModel и передаю родительский объект, я получаю следующую ошибку:

"Коллекция EntityCollection уже инициализирована. Метод InitializeRelatedCollection следует вызывать только для инициализации новой коллекции EntityCollection во время десериализации графа объектов."

Я видел много других сообщений от людей, борющихся с подобными проблемами, но не нашел решения. Разве это невозможно без создания пользовательского связующего для модели? Если у кого-то есть рабочий пример, я был бы очень признателен. По какой-то причине я могу перебрать дочернюю коллекцию и успешно выполнить TryUpdateModel на дочерних объектах, но когда я вызываю его на родительском объекте, выдается ошибка выше. В идеале я хотел бы вызвать его один раз для родителя и получить обновление всего дерева объектов из формы.

Вот код контроллера:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection formValues)
        {
            EFEntities ef = new EFEntities();
            ParentObject parent = ef.ParentObjects.SingleOrDefault(p => p.ID == id);

            if (ModelState.IsValid)
            {
                int i = 0;
                foreach (child in parent.ChildObjects)
                {
                    //this works fine
                    TryUpdateModel(child, "ChildObjects[" + i + "]"); 
                    i++;
                }

                //this blows up
                if (TryUpdateModel(parent)) 
                {                    
                    ef.SaveChanges();
                    return RedirectToAction("Details", new { id = parent.ID });
                }
            }
            return View(parent);
        }

Ответы [ 2 ]

1 голос
/ 29 апреля 2011

В конечном итоге я нашел более элегантное решение, но так и не вернулся, чтобы опубликовать его.Вот оно - извините за задержку:

if (ModelState.IsValid)
        {
            if (TryUpdateModel(parent, new[] "prop1", "prop2", "prop3" })) //specify parent-only properties to include
            {
                if (TryUpdateModel(parent.ChildObjects, "ChildObjects"))
                {
                    _ef.SaveChanges();
                    return RedirectToAction("Details", new { id = parent.ID })                    }
            }
        }
        return View(parent);

Я конвертирую этот код из реального приложения, поэтому я прошу прощения за любые опечатки.

1 голос
/ 19 апреля 2011

Спасибо за этот вопрос, хотя он не был дан ответ, он дал мне мой ответ. Лучшее, что я могу найти, - это (на вашем примере):

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection formValues)
        {
            EFEntities ef = new EFEntities();
            ParentObject parent = ef.ParentObjects.SingleOrDefault(p => p.ID == id);

            if (ModelState.IsValid)
            {
                int i = 0;
                foreach (child in parent.ChildObjects)
                {
                    //this works fine
                    TryUpdateModel(child, "ChildObjects[" + i + "]"); 
                    i++;
                }

                //exclude the collections and it won't blow up...
                if (TryUpdateModel(parent, "Parent", null, new string[] {"ChildObjects"})) 
                {                    
                    ef.SaveChanges();
                    return RedirectToAction("Details", new { id = parent.ID });
                }
            }
            return View(parent);
        }
...