ventajas framework first example español desventajas code entity-framework

entity-framework - first - entity framework nuget



Ya existe un objeto con la misma clave en ObjectStateManager. ObjectStateManager no puede rastrear múltiples objetos con la misma clave (4)

Básicamente, tengo una tabla que contiene algunas propiedades para una empresa. Esta es la tabla "maestra" y su ID se usa en muchas otras tablas. Básicamente encuentro su identificación a través de este método:

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

Necesito darles a los usuarios la posibilidad de actualizar varios detalles sobre ellos mismos almacenados en esta tabla, lo cual hice perfectamente bien, sin embargo, noté un gran agujero de seguridad.

Usando Tamper Data en Firefox (e imagino a Fidler / muchos otros), podría cambiar fácilmente la identificación oculta y modificar los detalles de otra compañía.

Para detener esto, agregué las siguientes líneas a la acción de modificación:

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

(Para su información, la Company es un modelo / POCO que representa a una empresa, y la propia company es la información del formulario).

Después de agregar esto, si edito la ID en los datos del formulario, funciona como se esperaba y aparece "Error de seguridad", sin embargo, si no hay un error y continúo, aparece el error en la pregunta.

"Ya existe un objeto con la misma clave en ObjectStateManager. ObjectStateManager no puede rastrear múltiples objetos con la misma clave".

Creo que esto es porque EF de alguna manera detecta y mantiene la primera extracción de datos, pero no estoy seguro de cómo corregirlo.

¿Algún consejo?

edit- --actualizar--

Si puedes entender lo que estoy tratando de lograr, ¿hay una mejor manera de evitar esto?


Acabo de ver este tema ayer. Debes desconectar cuco antes de la actualización. Mira la solución en esta answer


Como el error indica claramente, debe asegurarse de obtener el elemento existente y modificar los datos del elemento con información actualizada y guardarlo. No se encontrará con este problema si actualiza información muy específica y no información clave, como ID e ID de ForeignKey.
¡Debajo del código debería hacer el trabajo!

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

El uso será -

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); ...


Si carga la entidad desde el contexto, no puede volver a adjuntar una entidad con la misma clave. La primera entidad se conserva en el caché de contexto interno y el contexto solo puede contener una instancia con un valor clave dado por tipo (se denomina mapa de identidad y aquí lo describí en otra situación).

Puedes resolverlo separando la instancia anterior pero no es necesario. Si solo necesita guardar nuevos valores, puede usar esto:

  • ObjectContext API: context.YourEntitySet.ApplyCurrentValues(newEntity);
  • DbContext API: context.Entry(oldEntity).CurrentValues.SetValues(newEntity);

Solo un poco de ayuda para ti si no sabes cómo encontrar la oldEntity como lo oldEntity Ladislav:

var entityKey = context.NewEntitySet.Create().GetType().GetProperty("Id").GetValue(newEntity); factory.Entry(context.Set<NewEntityType>().Find(entityKey)).CurrentValues.SetValues(newEntity);