Ho un oggetto che ha una chiave memorizzata come GUID e un ID amichevole, come questo:
public class Job {
[Key]
public Guid Id { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int FriendlyId { get; set; }
public string Description { get; set; }
}
Tuttavia quando provo ad aggiornare la descrizione usando il mio metodo di aggiornamento:
public void Update(Job job, Job jobParam) {
if (job == null) {
throw new AppException("Job does not exist");
}
//Update job properties
job.Description = jobParam.Description;
_context.Job.Update(job);
_context.SaveChanges();
}
Ottengo un errore affermando:
System.Data.SqlClient.SqlException: impossibile aggiornare la colonna Identity 'FriendlyId'
Mi sono assicurato che l'oggetto corretto stia cercando di essere aggiornato, ma non riesco a capire perché friendlyID proverà ad aggiornarsi quando non è stato modificato. Quando guardo online, vedo che c'era un bug nel core 1.1 di EF che avrebbe causato questo problema, ma niente su 2.0 o su un valore che non fosse una chiave.
L'esatto comportamento delle proprietà generate in EF Core è ancora in fase di ottimizzazione. EF Core 2.0 ha introdotto due nuove proprietà dei metadati delle proprietà: BeforeSaveBehavior
e AfterSaveBehavior
. Non ci sono annotazioni di dati / API fluenti per l'impostazione e per impostazione predefinita sono implicite nella strategia di generazione del valore e se la proprietà fa parte della chiave. Allo stesso tempo influiscono sul comportamento delle operazioni di tracciamento.
Il problema qui è che per le colonne di identità (vale a dire ValueGeneratedOnAdd
) che non fanno parte di una chiave, AfterSaveBehavior
è Save
, che a sua volta rende il metodo Update
per contrassegnarle come modificate, che a sua volta genera un comando UPDATE
errato.
Per risolvere questo problema, devi impostare AfterSaveBehavior
questo modo (all'interno di OnModelCreating
):
modelBuilder.Entity<Job>()
.Property(e => e.FriendlyId)
.ValueGeneratedOnAdd()
.Metadata.AfterSaveBehavior = PropertySaveBehavior.Throw; // <--