Sto implementando una routine di importazione, in cui un utente incolla una specifica stringa formattata in un campo di input, che a sua volta viene trasformato in un'entità e quindi inserito in un database.
L'algoritmo controlla se l'entità esiste già e tenta di aggiornarlo o inserirlo nel database. L'inserimento funziona bene - l'aggiornamento fallisce.
//considered existing if Name and owning user match.
if (db.Captains.Any(cpt => cpt.Name == captain.Name && cpt.User.Id == UserId))
{
var captainToUpdate = db.Captains.Where(cpt => cpt.Name == captain.Name && cpt.User.Id == UserId).SingleOrDefault();
db.Entry(captainToUpdate).CurrentValues.SetValues(captain);
db.Entry(captainToUpdate).State = EntityState.Modified;
await db.SaveChangesAsync();
}
Il problema in questione è che, scritto in questo modo, tenta di aggiornare anche la chiave primaria, (l'id del captain
è 0, mentre captainToUpdate
ID captainToUpdate
è già impostato) che genera un'eccezione The property 'Id' is part of the object's key information and cannot be modified.
Di cosa ho bisogno di cambiare, quindi l'elemento viene aggiornato correttamente. Se può essere evitato, non voglio aggiornare ogni proprietà a mano, perché la tabella Captain contiene 30 colonne.
Non userei l'entità Captain
per trasferire i dati nell'interfaccia utente, ma un oggetto DTO che ha tutte le proprietà che si desidera copiare e non di più. È possibile copiare valori da qualsiasi oggetto. Tutte le proprietà corrispondenti saranno copiate, tutte le altre proprietà in captainToUpdate
non saranno interessate.
Quello che puoi fare è prima impostare l'ID di capitano in modo che sia uguale all'ID di captainToUpdate:
captain.Id = captainToUpdate.Id;
db.Entry(captainToUpdate).CurrentValues.SetValues(captain);
await db.SaveChangesAsync();