Как я могу заменить объект другим объектом с тем же ключом в первом подходе Entity Framework DB?

Сначала я программирую веб-приложение MVC 4, используя базу данных EF 5. У меня есть несколько, казалось бы, тривиальных проблем, для которых я не могу найти правильного решения. Эти проблемы связаны с менеджером состояния объекта.

В самом простом сценарии все работает нормально: я читаю сущности из базы данных с помощью Find, помещаю их в представление, жду ответа, воссоздаю сущность, записываю ее обратно с помощью Attach, EntityState.Modified и SaveChanges. Проблемы возникают, если при обработке запроса я еще раз получаю сущность из базы данных.

Я делаю это, если:
1. По какой-то причине я хочу проверить некоторые значения исходной сущности.
2. Некоторые из моих значений не нужно изменять, поскольку они идентифицируют сущность. Я поместил их в свое представление только для справки, используя DisplayFor. Конечно, восстановленная модель не имеет этих значений. Я получаю исходный объект из базы данных и в контроллере использую TryUpdateModel, чтобы объединить его с моделью из представления.

При вызове Attach я получаю исключение «Объект с таким же ключом уже существует в ObjectStateManager. ObjectStateManager не может отслеживать несколько объектов с одним и тем же ключом».

Если я использую Context.Entry(t).CurrentValues.SetValues(t); вместо DbSet.Attach(t);, я получаю следующее исключение:

Member 'CurrentValues' cannot be called for the entity of type 'Price' because the entity does not exist in the context. To add an entity to the context call the Add or Attach method of DbSet<Price>.

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

Есть ли способ добиться этого?


person R. Schreurs    schedule 05.04.2013    source источник
comment
плиз, кто-нибудь решил это. я схожу с ума по той же проблеме   -  person user853710    schedule 21.07.2013
comment
Я так и не решил ее. Вместо этого в некоторых случаях я создаю другой контекст. Возможное решение, которое я не проверял, представлено в объекте с тем же ключом уже существует в ObjectStateManager. ObjectStateManager не может отслеживать несколько объектов с одним и тем же ключом.. Я думаю, что проблема как-то связана с использованием Динамические прокси, поэтому, возможно, поиск дополнительной информации об этом также может вам помочь.   -  person R. Schreurs    schedule 22.07.2013
comment
это был тот же самый быстрый и грязный трюк, который я сделал   -  person user853710    schedule 22.07.2013
comment
У меня такая же проблема :(   -  person GMan    schedule 28.09.2014
comment
@GMan, я получил уведомление о ваших комментариях и добавил свой ответ на этот вопрос. Я надеюсь, что это помогает!   -  person R. Schreurs    schedule 27.10.2014
comment
Спасибо за это. Это помогает :)   -  person GMan    schedule 16.11.2014


Ответы (1)


В то же время я начал использовать подход Model First, поэтому я не совсем уверен, применимо ли следующее, но я думаю, что некоторые из них могут быть полезны.

  1. Выполняйте запросы с помощью someContext.someDbSet.AsNoTracking(), если вы просто хотите просмотреть некоторые данные, но не собираетесь обновлять базу данных изменениями. См. AsNoTracking в MSDN.
  2. Исключить некоторые свойства модели из обновления. Это поможет вам обновить, например. профиль пользователя без обновления хешированного пароля, хранящегося в той же модели.

    someContext.someDbSet.Attach(someModelInstance);
    var entry = substanceContext.Entry(someModelInstance);
    entry.State = EntityState.Modified;
    entry.Property("somePropertyToIgnore").IsModified = false;
    substanceContext.SaveChanges();
    

Если вы посмотрите на SQL, сгенерированный во втором решении, вы заметите, что поле somePropertyToIgore отсутствует в предложении SET.

person R. Schreurs    schedule 26.10.2014