Reputation: 427
hello community I have a problem when I try to edit a model it tells me that I am trying to duplicate the primary key and I don't know why this happens.
Error System.InvalidOperationException: The instance of entity type 'Cotizacion' cannot be tracked because another instance with the same key value for {'CotizacionId'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.
this is my controller code:
[HttpPut]
public async Task<ActionResult> Put(Cotizacion cotizacion)
{
var cotizacionoriginal = context.Cotizaciones.Where(x => x.CotizacionId == cotizacion.CotizacionId).FirstOrDefault();
cotizacionoriginal = cotizacion;
context.Update(cotizacion);
context.SaveChanges();
return NoContent();
}
this is my model cotizacion:
public class Cotizacion
{
[Key]
public Guid CotizacionId { get; set; }
public Guid InquilinoId { get; set; }
public int Folio { get; set; }
public DateTime? FechaCotizacion { get; set; }
public DateTime? FechaVencimiento { get; set; }
public DateTime? FechaCreacion { get; set; }
public DateTime? FechaModificacion { get; set; }
public bool EsBorrador { get; set; }
public double Total { get; set; }
public string Comentario { get; set; }
public bool Aceptada { get; set; }
public Guid CarritoId { get; set; }
public Guid ClienteId { get; set; }
public Guid? DireccionId { get; set; }
public Guid? ContactoId { get; set; }
public virtual Carrito Carrito { get; set; }
public virtual Cliente Cliente { get; set; }
public virtual Direccion Direccion { get; set; }
public virtual Contacto Contacto { get; set; }
}
this is my model cliente:
public class Cliente
{
public Guid ClienteId { get; set; }
public Guid InquilinoId { get; set; }
[Required(ErrorMessage = "El campo {0} es requerido")]
public string Nombre { get; set; }
[Required(ErrorMessage = "El campo Razón Social es requerido")]
public string Razon_social { get; set; }
[Required(ErrorMessage = "El campo {0} es requerido")]
public string Rfc { get; set; }
[Required(ErrorMessage = "El campo {0} es requerido")]
public string Email { get; set; }
public int Telefono { get; set; }
public int Celular { get; set; }
public bool Es_Cliente { get; set; }
public bool Es_Proveedor { get; set; }
public virtual List<Contacto> Contacto { get; set; } = new List<Contacto>();
public virtual List<Direccion> Direccion { get; set; } = new List<Direccion>();
public virtual List<ClienteTipodeConcepto> ClienteTipodeConcepto { get; set; } = new List<ClienteTipodeConcepto>();
public virtual List<ClienteConcepto> ClienteConcepto { get; set; } = new List<ClienteConcepto>();
public virtual Cliente Empresa { get; set; }
}
this is my model carrito:
public class ArticuloCarrito
{
[Key]
public Guid ArticuloCarritoId { get; set; }
public Guid ProductoId { get; set; }
public int Cantidad { get; set; }
public decimal PrecioPublico { get; set; }
public decimal Total// { get; set; }
{
get
{
return PrecioPublico * Cantidad;
}
}
public virtual Carrito Carrito { get; set; }
public virtual Producto Producto { get; set; }
}
public class Carrito
{
[Key]
public Guid CarritoId { get; set; }
public virtual ICollection<ArticuloCarrito> Articulos { get; set; }
public decimal Subtotal
{
get
{
decimal total = 0;
if (Articulos is null)
{
total = 0;
}
else
{
foreach (var item in Articulos)
{
total += item.Total;
}
}
return total;
}
}
public decimal IVA
{
get
{
double sub = Convert.ToDouble(Subtotal);
return (Convert.ToDecimal(sub * .16));
}
}
public decimal Total
{
get
{
double sub = Convert.ToDouble(Subtotal);
return (Convert.ToDecimal(sub * 1.16));
}
}
public DateTime UltimoAcceso { get; set; }
public int TiempoDeVidaEnSegundos { get; set; } = 1800;
}
also try an endpoint like this:
[HttpPut]
public async Task<ActionResult> Put(Cotizacion cotizacion)
{
var cotizacionDB = await context.Cotizaciones.FirstOrDefaultAsync(x => x.CotizacionId == cotizacion.CotizacionId);
if (cotizacionDB == null) { return NotFound(); }
cotizacionDB = mapper.Map(cotizacion, cotizacionDB);
await context.Database.ExecuteSqlInterpolatedAsync($"delete from Cotizaciones WHERE CotizacionId = {cotizacion.CotizacionId};");
cotizacionDB.Cliente = cotizacion.Cliente;
cotizacionDB.Carrito = cotizacion.Carrito;
await context.SaveChangesAsync();
return NoContent();
}
but it didn't work
my new try:
[HttpPut]
public async Task<ActionResult> Put(Cotizacion cotizacion)
{
var cotizacionoriginal = context.Cotizaciones.Where(x => x.CotizacionId == cotizacion.CotizacionId).FirstOrDefault();
cotizacionoriginal.Carrito= cotizacion.Carrito;
if (cotizacionoriginal != null)
{
context.Entry(cotizacionoriginal).State = EntityState.Detached;
}
context.Entry(cotizacion).State = EntityState.Modified;
await context.SaveChangesAsync();
return NoContent();
}
Upvotes: 0
Views: 1380
Reputation: 1628
The reason that you are running into this issue is due to the code in your controller. On this line you are tracking a Cotizacion entity
var cotizacionoriginal = context.Cotizaciones.Where(x => x.CotizacionId == cotizacion.CotizacionId).FirstOrDefault();
And on this line you are attempting to track another Cotizacion entity with the same key value.
context.Update(cotizacion);
Essentially you have three ways that you can handle this.
Option #1 Detach local entry and attach updated entry:
var cotizacionoriginal = context.Cotizaciones.Where(x => x.CotizacionId == cotizacion.CotizacionId).FirstOrDefault();
// check if local is not null
if (cotizacionoriginal != null)
{
// detach
_context.Entry(cotizacionoriginal).State = EntityState.Detached;
}
// set Modified flag in your entry
_context.Entry(cotizacion).State = EntityState.Modified;
// save
_context.SaveChanges();
Option #2 Update the individual properties you want to change
[HttpPut]
public async Task<ActionResult> Put(Cotizacion cotizacion)
{
var cotizacionoriginal = context.Cotizaciones.Where(x => x.CotizacionId == cotizacion.CotizacionId).FirstOrDefault();
cotizacionoriginal.Folio = cotizacion.Folio;
cotizacionoriginal.Total = cotizacion.Total; //Continue as required
context.Update(cotizacionoriginal );
context.SaveChanges();
return NoContent();
}
Option #3 Simply update that value if it's guaranteed that it will always exist and will never cause any issues (not recommended)
[HttpPut]
public async Task<ActionResult> Put(Cotizacion cotizacion)
{
context.Update(cotizacion);
context.SaveChanges();
return NoContent();
}
If you are attempt to update items within the Cotizacion type as well (for example Nombre inside the Cliente) then this won't work. You can update the reference to the Cliente inside the Cotizacion, but in order to update the subitems you will need to perform those separately.
Upvotes: 2