Как обновить реляционную базу TABELS?

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

Объект с таким же ключом уже существует в ObjectStateManager.

ObjectStateManager не может отслеживать несколько объектов с одним и тем же ключом.

Я работаю над реляционной базой данных. Ниже приведены 3 сущности и их связь:

         1    to   *        1   to    *
Ceremony -----------> Menu ------------> CourseOption

Все работает нормально, если я обновлю церемонию, которая уже содержитMenus а такжеCourseOptions, Проблема возникает, когда мы вставляем новыйMenu а такжеCourseOption запись в церемонии во время обновления. Чем я получил вышеупомянутое исключение.

Код C # для обновления существующей церемонии

public HttpResponseMessage PutCeremony(int id, Ceremony ceremony)
{
    if (ModelState.IsValid && id == ceremony.Id)
    {
       db.Entry(ceremony).State = EntityState.Modified;

       try
       {
           db.SaveChanges();
       }
       catch (DbUpdateConcurrencyException)
       {
           return Request.CreateResponse(HttpStatusCode.NotFound);
       }

       return Request.CreateResponse(HttpStatusCode.OK, ceremony);
    }
    else
    {
       return Request.CreateResponse(HttpStatusCode.BadRequest);
    }
}

Как я могу избавиться от этой проблемы? Пожалуйста помоги

РЕДАКТИРОВАТЬ

Сегодня я провожу целый день в этом, я прочитал много статей и вопросов о stackoverflow. я нашел этоonce a product is fetched from the Context, the context is keeping track of it так что почему вместо использования:

db.Entry(ceremony).State = EntityState.Modified;

я использовал

db.Entry(db.Ceremonies.Find(ceremony.Id)).CurrentValues.SetValues(ceremony);

Теперь, сделав это изменение, исключение исчезло, и свойства объекта Ceremony изменились должным образом. Но запись меню, связанная с церемонией, и запись CourseOptions не обновляются. Пожалуйста, дайте мне предложение, ребята. Я абсолютно новый в EF.

 Tom Rider29 окт. 2012 г., 12:14
 Tom Rider29 окт. 2012 г., 12:12
Нет, если я обновлю свойства объекта Ceremony, тогда с этим не возникнет никаких проблем, возникнет проблема, когда я изменю массив свойств меню (свойство Navigation на объект Menu). Если я добавляю новый объект меню или удаляю любой существующий, то изменения не происходят в базе данных
 Heki29 окт. 2012 г., 12:00
Итак, когда вы создаете новыйCeremonyдобавляешь новыеMenuс иCourseOtionили они уже существуют?
 Tom Rider29 окт. 2012 г., 12:03
да, во время создания новой церемонии пользователь может добавить меню и параметры курса, но если пользователь захочет добавить их (меню и выбор курса) позже, он может сделать это при редактировании церемонии. Но проблема возникает, когда мы добавляем новое меню во время обновления существующей церемонии
 gillyb29 окт. 2012 г., 11:57
Вы должны изменить название вопроса!
 Tom Rider29 окт. 2012 г., 12:06
Да, когда я добавляю новую церемонию, чем она добавляется должным образом без каких-либо проблем, проблема возникает только во время обновления существующей церемонии
 Heki29 окт. 2012 г., 12:04
Так что'не отказывает при создании новогоCeremony? Это'на самом деле невозможно увидеть чтопроисходит сceremony перед этим'с переданыPutCeremony, Что я'Я ловлю на то, что происходит, когда вы добавляете этиMenus.
 Heki29 окт. 2012 г., 12:08
Если вы беретеCeremony отdb и обновить его (пустьговорят, что естьName) с изменением вName и сохранить эти изменения, у вас тогда проблемы? Работайте с самого простого и прокладывайте путь к нужному коду.
 Tom Rider29 окт. 2012 г., 11:34
Эй, ребята, вопрос слишком сложный Или неясно, если позже, чем, пожалуйста, дайте мне знать

Ответы на вопрос(1)

только с одной дочерней коллекцией здесь:https://stackoverflow.com/a/5540956/270591 Если у вас есть внушительная детская коллекция, она еще сложнее.)

Не существует общего подхода или простого метода, такого как установка состояния вModified (он только помечает скалярные свойства как измененные) и надеется, что он сохранит все изменения графа объектов.

Детали, чтобы рассмотреть, чтобы осуществить такое обновление:

Ли пользовательСоздайте новые меню, когда меню добавляется к церемонии или он только устанавливает связь между церемонией исуществующий меню?Ли пользовательудалять существующее меню, когда меню удаляется из церемонии, или он только освобождает связь между церемонией и меню, но меню все еще должно существовать в базе данных (тогда FK должен быть обнуляемым)?Может ли пользователь изменять (скалярные) свойства меню в вашем представлении или он может только добавлять меню к церемонии или удалять их, не изменяя сами меню?Те же вопросы относятся к коллекции внуковCourseOptions каждого .Menu

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

можно изменить скалярные свойства церемонииможет удалить существующие меню из церемонии, которые должны быть удалены из базы данных, когда они удаляются, и связанныеCourseOptions следует также удалить, и каскадное удаление для этого отношения включено в базе данныхможет создавать и добавлять новые меню для церемонии, которые должны быть вставлены в базу данныхне может изменить скалярные свойства существующих менюне могу добавитьCourseOptions к существующемуMenu и не может удалить их изMenuмогу добавить новыйCourseOptions к новомуMenu (иCourseOptions должны быть вставлены вместе с новым меню)не может изменить скалярные свойства существующегоCourseOption

... код будет выглядеть так:

var ceremonyInDb = db.Ceremonies.Include(c => c.Menus)
    .Single(c => c.Id == ceremony.Id);

db.Entry(ceremonyInDb).CurrentValues.SetValues(ceremony);

foreach (var menuInDb in ceremonyInDb.Menus.ToList())
    if (!ceremony.Menus.Any(m => m.Id == menuInDb.Id))
        db.Menus.Remove(menuInDb);

foreach (var menu in ceremony.Menus)
    if (!ceremonyInDb.Menus.Any(m => m.Id == menu.Id))
        ceremonyInDb.Menus.Add(menu);

db.SaveChanges();

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

Ваш ответ на вопрос