Подтвердить что ты не робот

"Объект с тем же ключом уже существует в объекте ObjectStateManager..." возникает исключение при настройке состояния объекта для изменения

Я последовал за некоторыми примерами (включая такие книги, как "Pro ASP.NET MVC 3" и "Профессиональный ASP.NET MVC 3" ) для создания простых приложений ASP.NET MVC 3 с использованием EF 4.1 (поскольку я новичок в этих технологии).

Я использую следующий репозиторий (один экземпляр его используется всеми методами действий контроллера) для доступа к БД:

public class ProductRepository : IProductRepository
    {
        private readonly EFDbContext _context = new EFDbContext();

        #region Implementation of IProductRepository       

       ....

        public void SaveProduct(Product product)
         {           
            if (product.ProductId == 0)
            {
                _context.Products.Add(product);
            }
            else
            {
                _context.Entry(product).State = EntityState.Modified;

            }

            _context.SaveChanges();
        }

....
}

Этот репозиторий выполняет обновление, как показано в примерах, которые я использовал.

Класс продукта:

public class Product
    {       
        public int ProductId { get; set; }       
        public string Name { get; set; }      
        public string Description { get; set; }     
        public decimal Price { get; set; }
        public string Category { get; set; }
}

В случае обновления продукта я получаю исключение "Объект с тем же ключом уже существует в ObjectStateManager. ObjectStateManager не может отслеживать несколько объектов с одним и тем же ключом

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

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

4b9b3361

Ответ 1

После поиска часов для решения я нашел тот, который кажется подходящим после достаточного чтения.

Исправление:

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

В принципе, извлеките запись из контекста и вызовите:

var currentProduct = _context.Products.Find(product.ProductId);    
_context.Entry(currentProduct).CurrentValues.SetValues(product);

Это похоже на плохую идею и что-то, что я всегда ненавидел в EF в своих предыдущих разработках, но в соответствии с Ladislav Mrnka (который прекрасно отвечает на каждый вопрос, связанный с EF на Stackoverflow) в этом сообщении:

Структура сущностей и пул соединений

EF будет хранить запрос для объекта внутри, так что в идеале он уже будет там, и он не будет делать дополнительный вызов обратно в базу данных.

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

Надеюсь, что это поможет.

Ответ 2

Похоже, вы не обновляете product.ProductId, когда элемент сохраняется в первый раз. Это означает, что, когда вы вернетесь, чтобы снова сохранить элемент, он снова добавляет его в контекст, следовательно, ошибку.

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

Ответ 3

С точки зрения Generics, вот как я решаю ту же самую проблему совсем недавно:

    public TEntity Update(TEntity model, bool persist)
    {
        if (model == null)
        {
            throw new ArgumentException("Cannot update a null entity.");
        }

        var updateModel = Get(model.Id);

        if (updateModel == null)
        {
            return model;   
        }

        this.context.Entry<TEntity>(updateModel).CurrentValues.SetValues(model);

        this.Save(persist);

        return model;
    }