Объект с таким ключом уже существует в ObjectStateManager. ObjectStateManager не может отслеживать несколько объектов с одним ключом
в принципе, у меня есть таблица, которая содержит несколько свойств для компании. Это "главная" таблица, и их идентификатор используется во многих других таблицах. Я в основном найти их идентификатор с помощью этого метода:
private Company currentcompany()
{
Company cuco = db.Companies.Single(x => x.username == User.Identity.Name);
return cuco;
}
мне нужно дать пользователям возможность обновлять различные сведения о себе, хранящиеся в этой таблице, что я сделал отлично - однако я заметил большую дыру в безопасности!
используя данные Tamper в Firefox (и я представляю Fidler / многие другие), я мог бы легко изменить скрытый идентификатор и изменить другие детали компании.
чтобы остановить это, я добавил следующие строки, чтобы изменить действия:
Company cuco = currentcompany();
if (company.id != cuco.id)
{
return Content("Security Error");
}
(к вашему сведению -Company
это модель / POCO, представляющая компанию, и company
сама форма данных.)
после добавления этого, если я редактирую идентификатор в данных формы, он работает как ожидалось и вызывает "ошибка безопасности", однако, если ошибки нет, и я продолжаю, я получаю ошибку в вопросе.
"объект с таким ключом уже существует в ObjectStateManager. ObjectStateManager не может отслеживать несколько объектов с одним и тем же ключом."
Я считаю, что это потому, что EF каким-то образом обнаруживает и сохраняет первый запрос данных, но я просто не уверен, как его исправить.
какие-либо советы?
изменить- --обновление--
если вы можете понять, что я пытаюсь достичь, есть ли лучший способ обойти это?
4 ответа:
Если вы загружаете объект из контекста, вы не можете снова присоединить объект с тем же ключом. Первая сущность все еще хранится во внутреннем кэше контекста, и контекст может содержать только один экземпляр с заданным значением ключа для каждого типа (он называется identity map и Я описал его здесь в другой ситуации).
вы можете решить ее, отсоединив прежний экземпляр, но вам это не нужно. Если вам нужно только сохранить новые значения вы можете использовать это:
- ObjectContext API:
context.YourEntitySet.ApplyCurrentValues(newEntity);
- DbContext API:
context.Entry(oldEntity).CurrentValues.SetValues(newEntity);
просто немного помочь, если вы не знаете как найти
oldEntity
как по Ладиславу:var entityKey = context.NewEntitySet.Create().GetType().GetProperty("Id").GetValue(newEntity); factory.Entry(context.Set<NewEntityType>().Find(entityKey)).CurrentValues.SetValues(newEntity);
Как ясно говорится в ошибке - вы должны убедиться, что сделать существующие элемент и изменить данные элемента С обновленной информацией и сохранить его. Вы не столкнетесь с этой проблемой, если вы обновите очень конкретную информацию, а не ключевую информацию, такую как 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); ...
только что видел этот вопрос вчера. Вам нужно отсоединить cuco перед обновлением. Проверьте решение в этом ответ