CRUD-операции родитель / потомок на одной странице редактирования MVC5

1

У меня есть проект MVC 5 с использованием EF6 Code First. Он включает в себя модели, содержащие списки сложных дочерних объектов. Мне нужно иметь возможность добавлять, обновлять и удалять дочерние объекты на странице редактирования родительских объектов, одновременно сохраняя изменения родительского объекта.

Я столкнулся с дилеммой о том, как эти операции должны обрабатываться в контроллере. Вот соответствующий код.

Модели:

public class Parent
{
    public int Id {get;set;}
    //other properties
    public virtual IList<Child> Children {get;set;}
}

public class Child
{
    public int Id {get;set;}
    //other properties
    public int Parent_Id {get;set;}
    [ForeignKey("Parent_Id")]
    public virtual Parent Parent {get;set;}
    [NotMapped]
    public bool toBeDeleted {get;set;}
}

контроллер:

[HttpPost]
public ActionResult Edit([Bind(Include = "Id, Children")] Parent p)
{
    ...
    //For some reason children are brought in with Parent_Id = null.
    //Manually resetting it fixes this issue.
    //Needs to be set before parent = modified for referential integrity
    foreach(var c in p.Children)
    {
        c.Parent_Id = p.Id;
    }
    context.Entry(p).State = EntityState.Modified;
    for(int i = 0; i < p.Children.Count; i++)
    {
        if(p.c[i].toBeDeleted)
        {
            Child childToDelete = context.Children.Find(p.c[i].Id);
            context.Entry(childToDelete).State = EntityState.Deleted;
            i--;
        }
        else
        {
            context.Entry(p.c[i]).State = p.c[i].Id > 0 ? EntityState.Modified : EntityState.Added;
        }
    }
    context.SaveChanges();
    ...
}

Мне пришлось включить "i--" после удаления, потому что с уже установленным модифицированным родителем все дочерние объекты, помеченные для удаления, были немедленно удалены из списка, который выкидывал цикл. (У меня первоначально был цикл foreach, но эта проблема вызвала ошибки, когда размер коллекции изменился в середине цикла)

В то время как у меня есть работы, это похоже на исправление лоскутного одеяла. Мне кажется, что должен быть лучший способ реализовать это, а не вручную уменьшать итератор в цикле for после каждого удаления, чтобы поддерживать правильно выстроенные элементы. Есть лучший способ сделать это? Есть ли способ установить состояние объекта для каждого объекта отдельно, не затрагивая состояние связанных объектов?

Теги:
entity-framework
asp.net-mvc
asp.net-mvc-5

1 ответ

1
Лучший ответ

Как насчет:

p.Children.Where(m => m.toBeDeleted).ToList().ForEach(m => p.Children.Remove(m));

Просто удалив дочерние элементы из коллекции, Entity Framework отметит их для удаления.

Кроме того, для вашего условия добавления, если вы добавили скрытое поле для Parent_Id (что вам нужно, если нет), то у детей будет установлен Parent_Id, если только они не являются новыми. Если они новы, то просто из-за того, что они находятся в коллекции " Children Parent, они будут добавлены, а свойство Parent_Id будет автоматически установлено Entity Framework. Скорее всего, ваша проблема заключалась в попытке сохранить существующих детей, у которых были Parent_Id свойства Parent_Id, поскольку они не были отправлены. Это приведет к ошибке целостности, поскольку он выглядит как Entity Framework, как будто вы хотите, чтобы Parent_Id был изменен на null.

  • 0
    Это довольно круто. Единственная проблема, которую я заметил, это то, что Remove фактически не удалял объекты ... он просто отсоединял их от родителя. Когда я запросил базу данных напрямую, они все еще были там с NULL Parent_Id. Я поиграл с этим и изменил эту часть на .ForEach (m => context.Entry (m) .State = EntityState.Deleted); который, казалось, решил эту проблему. Кроме того, вскоре после публикации я заметил, что забыл добавить скрытое поле для внешнего ключа =) Мне придется изменить свой скрипт AddNew, чтобы установить значение этого поля в соответствии с тем, каким оно должно быть при добавлении нового дочернего элемента. на страницу
  • 0
    Интересно. Если он не удалял их при удалении из коллекции, это означает, что они действительны сами по себе: т. Parent_Id Столбец Parent_Id значение NULL. Если они никогда не должны существовать вне связи с родителем, то вам следует убедиться, что это столбец, который не может быть равен нулю. Затем они обязательно будут удалены, если вы нарушите отношения. Однако, учитывая, что столбец обнуляем, я понятия не имею, почему вы ранее получали ошибки целостности.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню