Esiste una best practice per fare una copia di un'entità, apportando alcune modifiche ad essa in base all'input dell'utente e quindi reinserirla nel database?
Alcuni altri thread Stackoverflow hanno menzionato che EF gestirà l'inserimento di nuovi oggetti anche se la stessa chiave primaria esiste nel database, ma non sono sicuro che sia così che EF Core lo gestirà. Ogni volta che provo a copiare un oggetto, ottengo un errore
Cannot insert explicit value for identity column in table when IDENTITY_INSERT is set to OFF
Fondamentalmente ho solo bisogno di un modo pulito per copiare un oggetto, apportare alcune modifiche ad esso in base all'input dell'utente, e quindi inserire quella copia nel database, e avere l'auto-incremento corretto. Esiste una best practice o un modo semplice per farlo senza dover impostare manualmente le proprietà su null o empty?
EDIT: codice di esempio per il recupero dell'oggetto dal database:
public Incident GetIncidentByIdForCloning(int id)
{
try
{
return _context.Incident.Single(i => i.IncidentId == id);
}
catch
{
return null;
}
}
Codice dopo il recupero dell'oggetto (Poiché alcuni campi sono generati automaticamente come RowVersion che è un Timestamp):
public IActionResult Clone([FromBody]Incident Incident)
{
var incidentToCopy = _incidentService.IncidentRepository.GetIncidentByIdForCloning(Incident.IncidentId);
incidentToCopy.IncidentTrackingRefId = _incidentService.IncidentRepository.GetNextIdForIncidentCategoryAndType(
Incident.IncidentCategoryLookupTableId, Incident.IncidentTypeLookupTableId).GetValueOrDefault(0);
incidentToCopy.RowVersion = null;
incidentToCopy.IncidentId = 0; //This will fail with or without this line, this was more of a test to see if manually setting would default the insert operation, such as creating a brand new object would normally do.
incidentToCopy.IncidentCategoryLookupTableId = Incident.IncidentCategoryLookupTableId;
incidentToCopy.IncidentTypeLookupTableId = Incident.IncidentTypeLookupTableId;
var newIncident = _incidentService.IncidentRepository.CreateIncident(incidentToCopy);
...
Mi rendo conto che potrei creare un oggetto completamente nuovo e fare la copia a sinistra, ma ciò sembra terribilmente inefficiente e voglio sapere se EF Core offre soluzioni migliori.
Quindi ho passato il thread "Possibile duplicato" un po 'più di quello che ho fatto quando inizialmente mi sono imbattuto in esso prima di crearlo, e c'era una soluzione non così elevata che ho trascurato che essenzialmente prendevo tutti i valori a una volta quando si recupera l'oggetto dal database e non recupera un riferimento a quell'oggetto nel processo. Il mio codice ora sembra qualcosa del genere:
try
{
var incidentToCopy = _context.Incident.Single(i => i.IncidentId == id);
return (Incident) _context.Entry(incidentToCopy).CurrentValues.ToObject();
}
Nella classe IncidentRepository
prova a ottenere l' Incident
utilizzando AsNoTracking
e dovrebbe essere tracciato come una nuova entità quando viene aggiunto.
public void Clone(int id)
{
// Prevent tracking changes to the object.
var incident = _context.AsNoTracking().SingleOrDefault(i => i.Id == id);
// Setting back to 0 should treat the object Id as unset.
incident.Id = 0;
// Add the Incident while it is untracked will treat it as a new entity.
_context.Incidents.Add(incident);
_context.SaveChanges();
}