Почему я сталкиваюсь со всеми препятствиями для простого обновления в EF?

У меня есть удостоверение личности со мной, и у меня есть имя со мной. Итак, по сути, мой метод имеет только эти параметры:

public void Foo(int id, string name)
{
}

и у меня есть эта часть логики внутри метода:

User user = new User(){ Id = id, Name = name };
Db.Entry(user).State = System.Data.EntityState.Modified;
Db.SaveChanges();

Вот и все. Ничего фантастического. Я получаю эту ошибку: "An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key"

и этот ответ Ладислава Мрнки: Объект с таким же ключом уже существует в ObjectStateManager. ObjectStateManager не может отслеживать несколько объектов с одним и тем же ключом

предлагает использовать context.Entry(oldEntity).CurrentValues.SetValues(newEntity);, но на самом деле у меня нет с собой oldEntity. Может ли кто-нибудь просто сказать мне, как мне обновить только 1 свойство пользователя? Я схожу с ума.


person Jack    schedule 06.08.2012    source источник
comment
почему бы не обновить с помощью выбора из сущности вместо System.Data.EntityState.Modified;   -  person COLD TOLD    schedule 06.08.2012
comment
У меня нет опыта работы с кодом (и поэтому я не буду публиковать ответ), но относится ли Db выше к контексту базы данных? Если это так, то контексты в мирах «сначала модель» и «сначала база данных» разрабатываются как недолговечные объекты, основанные на шаблоне «единица работы». Почему бы не создать новый контекст для выполнения этой операции?   -  person Adam Robinson    schedule 06.08.2012
comment
@COLD TOLD: Потому что я хочу, чтобы это было эффективно. Я не хочу запускать 2 запроса только ради обновления одного свойства из нескольких десятков свойств, которые у меня есть в моей пользовательской модели.   -  person Jack    schedule 06.08.2012
comment
@AdamRobinson: Спасибо. Но это, кажется, не работает.   -  person Jack    schedule 06.08.2012
comment
Можете ли вы опубликовать больше кода? Опубликованный код в порядке.   -  person LuckyStrike    schedule 06.08.2012
comment
@LuckStrike: это единственный фрагмент кода. Больше нечего постить :). Просто считайте Db экземпляром DbContext и все. Я не думаю, что здесь требуется публикация моей модели пользователя.   -  person Jack    schedule 06.08.2012
comment
@Jack: Вы не показываете, где создаете Db.   -  person Adam Robinson    schedule 06.08.2012
comment
@Adam: я создаю только один раз для каждого запроса, после создания я сохраняю его внутри HttpContext.Items. Следовательно, даже если я делаю несколько запросов к БД, он использует один и тот же DbContext. Это помогает?   -  person Jack    schedule 06.08.2012


Ответы (1)


Я создаю только один раз для каждого запроса, после создания я сохраняю его внутри HttpContext.Items. Следовательно, даже если я делаю несколько запросов к БД, он использует один и тот же DbContext. Это помогает?

Если какой-либо из этих «множественных запросов к БД» загружает пользователя с одним и тем же идентификатором, вы получите это исключение. Попробуйте использовать это:

public void Foo(int id, string name) {
   var user = Db.Users.Local.SingleOrDefault(u => u.Id == id);
   if (user == null) {
      user = new User { Id = id };
      Db.Users.Attach(user);
   } 

   user.Name = name;
   Db.SaveChanges();
}

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

person Ladislav Mrnka    schedule 06.08.2012
comment
Разве это не обновит пользователя только в том случае, если вы создадите и присоедините этот объект-заглушку? Если у вас есть существующий пользователь, вы не отмечаете его как измененного. - person John H; 06.08.2012
comment
@JohnH: он вносит изменения в подключенного пользователя, поэтому вам не нужно менять его состояние - EF должен обнаружить изменение. - person Ladislav Mrnka; 06.08.2012
comment
Так и есть! Я всегда предполагал, что мы должны делать это для всего, кроме случаев, когда мы специально присоединяем сущность. Спасибо. - person John H; 06.08.2012
comment
Ладислав Мрнка снова спешит на помощь! - person Jack; 06.08.2012
comment
@Ladislav: Это также необходимо для удаления? Короче говоря, это требуется каждый раз? Местный? - person Jack; 06.08.2012
comment
@Джек: Да. У вас никогда не может быть двух экземпляров сущности с одним и тем же ключом, прикрепленным к одному и тому же экземпляру контекста. - person Ladislav Mrnka; 06.08.2012