Sto cercando di recuperare una riga dal database, cambiando determinate colonne in essa e aggiungendola come nuova riga (Entity Framework Core),
Ma mi sta dando errore
Impossibile inserire il valore esplicito per la colonna Identity nella tabella 'Audit_Schedules' quando IDENTITY_INSERT è impostato su OFF.
Questa tabella ha una chiave primaria "ScheduleId"
Di seguito è il mio codice
AuditSchedules _schedules = new AuditSchedules();
using (var ctx = new QuestionnaireEntities(_configuration))
{
_schedules = ctx.AuditSchedules.Where(x => x.ScheduleId == model.ScheduleID).SingleOrDefault();
_schedules.StaffId = model.TransferedAuditorCode;
_schedules.StaffName = model.TransferedAuditorName;
_schedules.FromDate = _schedules.ToDate = Convert.ToDateTime(model.TransferedScheduleDate);
ctx.AuditSchedules.Add(_schedules);
ctx.SaveChanges();
_subschedules = ctx.AuditSubSchedule.Where(x => x.SubScheduleId == model.SubScheduleID).SingleOrDefault();
_subschedules.IsHoliDay = "Y";
_subschedules.HolidayType = model.HolidayType;
_subschedules.TransferedScheduleId = _schedules.ScheduleId.ToString();
ctx.AuditSubSchedule.Update(_subschedules);
ctx.SaveChanges();
}
Errore
ctx.AuditSchedules.Add(_schedules);
Per prima cosa ho pensato al suo valore in conflitto di Schedule_ID e non in grado di aggiungere la chiave primaria duplicata, ma Schedule_ID è il campo generato automaticamente, quindi questo problema non dovrebbe verificarsi
Ho anche provato a impostarlo su un valore diverso
_schedules.ScheduleId = 0;
ma non inserisce. Come posso replicare una riga con poche modifiche (voglio aggiungere una nuova riga ma i valori modificati)
Il comportamento EF core con valori generati automaticamente sull'inserto è diverso da EF6.
Innanzitutto, la proprietà deve avere il valore predefinito ( 0
) per poter essere generata automaticamente. Ciò consente l'inserimento di identità che non era possibile in EF6.
In secondo luogo, l'entità aggiunta non dovrebbe essere già tracciata dal contesto, perché altrimenti il contesto mantiene internamente alcune informazioni che la chiave dell'entità è stata impostata e includerà il valore (pari a 0
) nel comando INSERT
generato, che a sua volta causa la eccezione che stai ricevendo.
Per raggiungere l'obiettivo, prima di chiamare il metodo Add
:
Per prima cosa assicurati che l'entità non sia tracciata utilizzando la query No-tracking quando la ottieni
_schedules = ctx.AuditSchedules
.AsNoTracking() // <--
.Where(x => x.ScheduleId == model.ScheduleID)
.SingleOrDefault();
o distaccandolo esplicitamente
ctx.Entry(_schedules).State = EntityState.Detached;
Quindi resettare il PK
_schedules.ScheduleId = 0;
Fai altre modifiche e infine chiama
ctx.AuditSchedules.Add(_schedules);
Funzionerà per entità semplici senza proprietà di navigazione / FK. Per il grafo di entità complessa non si dovrebbe utilizzare alcuna query di tracciamento e quindi lavorare con esso allo stesso modo con i grafici di entità distaccati.
L'errore è semplice, perché aggiungi l'inserto identità come parte dell'inserto. Se è identità, deve essere generata automaticamente. Quindi, spegnere prima di inserire e poi accenderlo. O fallo generare automaticamente.
Questo errore sarà lo stesso se si tenta di inserire gli stessi dati dal server SQL. Questo è fondamentalmente propagato dal server SQL.
Se non si desidera che un ID venga generato dal database, è necessario utilizzare l'attributo DatabaseGenerated sul modello, come in
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ScheduleId {get;set;}
Se vuoi che l'identità sia inserita puoi provare la tecnica qui