Объект с таким же ключом уже существует в ObjectStateManager. ObjectStateManager не может отслеживать несколько объектов с одним и тем же ключом - PullRequest
59 голосов
/ 17 мая 2011

По сути, у меня есть таблица, которая содержит несколько свойств для компании.Это «главная» таблица, и ее идентификатор используется во многих других таблицах.Я в основном нахожу их ID с помощью этого метода:

private Company currentcompany()
    {
        Company cuco = db.Companies.Single(x => x.username == User.Identity.Name);
        return cuco;
    }

Мне нужно дать пользователям возможность обновлять различные данные о себе, хранящиеся в этой таблице, что я сделал совершенно хорошо - однако я заметил большую дыру в безопасности!

Используя данные несанкционированного доступа в Firefox (и я представляю Фидлера / многих других), я мог бы легко изменить скрытый идентификатор и изменить сведения о других компаниях.

Чтобы остановить это, я добавил следующие строкидля действия изменения:

        Company cuco = currentcompany();

        if (company.id != cuco.id)
        {
            return Content("Security Error");
        }

(FYI - Company - это модель / POCO, представляющая компанию, а company - это данные формы.)

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

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

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

Любой совет?

edit- --update -

Если вы можете понять, что япытаюсь добиться, есть ли лучший способ обойти это?

Ответы [ 4 ]

149 голосов
/ 18 мая 2011

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

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

  • API ObjectContext: context.YourEntitySet.ApplyCurrentValues(newEntity);
  • DbContext API: context.Entry(oldEntity).CurrentValues.SetValues(newEntity);
5 голосов
/ 17 мая 2013

Просто небольшая помощь для вас, если вы не знаете, как найти oldEntity, как считает Ладислав:

var entityKey = context.NewEntitySet.Create().GetType().GetProperty("Id").GetValue(newEntity);

factory.Entry(context.Set<NewEntityType>().Find(entityKey)).CurrentValues.SetValues(newEntity);
1 голос
/ 18 июля 2014

Как ясно указывает на ошибку - вам нужно получить существующий элемент и изменить данные элемента с обновленной информацией и сохранить ее. Вы не столкнетесь с этой проблемой, если обновите очень конкретную информацию, а не ключевую информацию, такую ​​как ID и ForeignKey ID
Ниже код должен сделать работу!

 public virtual void Update(TEntity entity)
    {
        _context.Entry(entity).State = EntityState.Modified;

        this._context.SaveChanges();
    }

Использование будет -

 public async Task<bool> UpdateVendorItem(string userId, Vendor modified)
    {

        try
        {
            var existing = await this.GetVendors().SingleOrDefaultAsync(a => a.Id == modified.Id);


            //Set updated info
            existing.VendorName = modified.VendorName;

            //Update address information
            existing.Address.AddressLine1 = modified.Address.AddressLine1;
            ... 

            await _vendorRepository.UpdateAsync(existing);

    ...
0 голосов
/ 17 мая 2011

Только что видел этот вопрос вчера. Вам необходимо отсоединить cuco перед обновлением. Проверьте решение в этом ответе

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...