Ho avuto un problema con l'impostazione dei valori prima di salvare un'entità aggiunta. Quando non cambio i valori delle entità che salva senza problemi.
L'errore che ottengo è questo:
SqlException: impossibile inserire il valore esplicito per la colonna Identity nella tabella 'TableName' quando IDENTITY_INSERT è impostato su OFF.
Sto usando .net Core 2.1 ei miei pacchetti di nuget sono tutti aggiornati.
Il seguente codice funziona correttamente in Entity Framework per .NET Framework
public override int SaveChanges()
{
try
{
int userId = currentUser.UserId;
IEnumerable<EntityEntry> addedEntities = ChangeTracker.Entries()
.Where(e => e.State == EntityState.Added && e.CurrentValues.ToObject() is ModelBase)
.Select(e => e);
foreach (var e in addedEntities)
{
var clE = e.CurrentValues.ToObject() as ModelBase;
if (clE != null)
{
clE.CreatedOn = DateTime.Now;
clE.CreatedBy = userId;
}
// When I delete this line, it works without a problem
// but it doesn't set the values obviously
e.CurrentValues.SetValues(clE);
}
return base.SaveChanges();
}
catch (Exception dbEx)
{
Exception raise = dbEx;
throw raise;
}
}
Qualche idea su cosa sto facendo male?
Grazie Chris
La documentazione del metodo ToObject
afferma:
Crea un'istanza del tipo di entità e imposta tutte le sue proprietà utilizzando i valori di questo oggetto.
In altre parole, il metodo crea una nuova istanza di entità e la popola con i valori correnti dell'entità tracciata.
Si noti che nel momento in cui si aggiunge l'entità al contesto, EF genera valori temporanei per la proprietà PK dell'identità, pertanto ToObject
copia anche tale valore.
Quindi SetValues
copia tutte le proprietà dell'oggetto passato, incluso il PK, ma ora il valore PK è contrassegnato come persistente (lo stesso accade se si imposta esplicitamente il valore PK su un valore diverso da quello predefinito 0).
L'effetto netto di tutto questo è che EF proverà ad inserire un valore esplicito nella chiave PK, che normalmente è disabilitata (richiede abilitazione speciale), quindi l'eccezione che si ottiene.
La soluzione è non utilizzare ToObject
/ SetValues
, ma modificare l'entità tracciata effettiva, che è accessibile tramite la proprietà Entity
:
var addedEntities = ChangeTracker.Entries()
.Where(e => e.State == EntityState.Added)
.Select(e => e.Entity)
.OfType<ModelBase>();
foreach (var e in addedEntities)
{
// Here you modify the actual entity instance, so the values
// you set will be considered by the base.SaveChanges() call
e.CreatedOn = DateTime.Now;
e.CreatedBy = userId;
}