Удаление объекта chlid из коллекции с помощью MVC3 Entity Framework 4.3. Сначала код - PullRequest
0 голосов
/ 22 марта 2012

Я нашел множество постов с очень похожими проблемами, как у меня, но все они, похоже, используют метод DeleteObject(), который, кажется, не существует в версии EF, которую я использую! (хотя это более чем вероятно, я смотрю в неправильных местах)

Во всяком случае, моя проблема. У меня есть два класса, User и Email, где у пользователя может быть много писем. У меня есть форма для редактирования, которая, к счастью, позволит мне редактировать все адреса электронной почты, прикрепленные к каждому пользователю. Я хотел бы разрешить удаление каждого адреса электронной почты, просто очистив текстовое поле в форме редактирования (это будет сделано с помощью функции JavaScript, вызываемой кнопкой удаления, связанной с каждым полем позже). С этой целью, когда данные отправляются обратно, я перебираю все адреса электронной почты и проверяю, имеет ли свойство address значение null, после чего я хочу полностью удалить этот объект Email. Ниже мой контроллер редактирования, который (не) занимается бизнесом:

[HttpPost]
public ActionResult Edit(int id, User User)
{
    try
    {
        foreach (Email Email in User.Emails)
        {
            if (Email.Address == null)
            {
                User.Emails.Remove(Email);
            }
            else
            {
                db.Entry(Email).State = EntityState.Modified;
            }
        }
        db.Entry(User).State = EntityState.Modified;
        db.SaveChanges();

        return RedirectToAction("Index");
    }
    catch
    {
        return RedirectToAction("Index");
    }
}

Это работает до некоторой степени, используя отладчик, я могу видеть, что он довольно удачно удаляет объект Email из User, но как только он это сделает, однажды он выдаст исключение, когда попытается повторить цикл снова:

Message=Collection was modified; enumeration operation may not execute.

мой вопрос: каков правильный метод удаления объекта Email не только из User, но и из моей базы данных тоже?

Заранее спасибо; -)

EDIT:

Я изменил свой контроллер, чтобы создать два списка, один для Emails с адресом и, а другой для тех, где адрес нулевой, и вместо этого перебрать их:

[HttpPost]
public ActionResult Edit(int id, User User)
{
    try
    {
        var notNullEmails = User.Emails.Where(e => e.Address != null).ToList();
        foreach (Email Email in notNullEmails)
        {
            db.Entry(Email).State = EntityState.Modified;
        }
        var isNullEmails = User.Emails.Where(e => e.Address == null).ToList();
        foreach (Email Email in isNullEmails)
        {
            db.Emails.Remove(Email);
        }
        db.Entry(User).State = EntityState.Modified;
        db.SaveChanges();

        return RedirectToAction("Index");
    }
    catch
    {
        return RedirectToAction("Index");
    }
}

Но это привело к этому исключению:

Message=The object cannot be deleted because it was not found in the ObjectStateManager.

Таким образом, я адаптировал foreach, используемый для нулевых адресов, для явного извлечения электронного письма, подлежащего удалению, в контекст следующим образом:

var isNullEmails = User.Emails.Where(e => e.Address == null).ToList();
foreach (Email Email in isNullEmails)
{
    Email EmailToDelete = db.Emails.Find(Email.Id);
    db.Emails.Remove(EmailToDelete);
}

Но это приводит к этому исключению:

Message=Value cannot be null.

Я думаю, что добираюсь туда благодаря вам, ребята, но я мог бы использовать немного больше помощи, пожалуйста: -)

Ответы [ 3 ]

2 голосов
/ 22 марта 2012

У вас есть две разные проблемы:

Во-первых, вы не можете удалять элементы из коллекции во время итерации коллекции.Итерируйте через копию List, которую uoi делает с помощью .ToList ().

Другой способ - вызов метода Remove (), который вы вызываете, только удаляет связь с пользователем, но не удаляет его из базы данных.Это приведет к ошибке ссылочной целостности, если база данных ее принудительно исполнит.

Вместо этого вы хотите вызвать Remove для электронных писем DbSet.

context.emails.Remove(email);

Remove () - метод, используемыйDbContext.DeleteObject и RemoveObject являются более старыми / альтернативными API

0 голосов
/ 18 апреля 2013

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

foreach(Email email in User.Emails)
{
    if(string.IsNullOrEmpty(email.Address))
    {
        db.Entry(email).State = System.Data.EntityState.Deleted;
    }
}
db.SaveChanges();

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

0 голосов
/ 17 апреля 2013

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


int i = User.Emails.Count - 1;
while (true)
{
  if (i<0)
  {
     break;
  }
  Db.Emails.DeleteObject(User.Emails.ElementAt<Email>(i));
  i--;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...