Ad esempio, ho la prossima tabella:
CREATE TABLE Person (
id int IDENTITY(1,1) NOT NULL PK,
firstName nvarchar(20) NOT NULL,
lastName nvarchar(30) NOT NULL,
birtdate datetimeoffset(7) NOT NULL,
age int,
height int,
)
C'è una parte della mappatura delle entità:
public void Configure(EntityTypeBuilder<Person> builder)
{
...
builder.HasKey(k => k.Id);
builder.Property(k => k.Id)
.ValueGeneratedOnAdd()
.IsRequired();
...
}
Ho il server MS SQL con quella tabella sul lato client e la stessa tabella sul lato server. Il mio programma recupera i dati dalla tabella sul client e li invia al server in cui i dati vengono aggiunti al database. Non ci sono problemi durante il recupero dei dati, ma quando provo ad inserire i dati ottengo l'errore:
SqlException: Cannot insert explicit value for identity column in table 'Person' when IDENTITY_INSERT is set to OFF.
nonostante .ValueGeneratedOnAdd()
Quando recupero i dati, ottengo entità con proprietà ID piene (1, 2, 3 ecc.) Ma penso che non abbia importanza.
Quando recupero i dati, ottengo entità con proprietà ID piene (1, 2, 3 ecc.) Ma penso che non abbia importanza.
In realtà ha importanza ed è la causa del problema. ValueGenerated
non ha effetto per le proprietà che hanno impostato valore sul valore non predefinito per il tipo ( null
per i tipi nullable, 0
per i tipi numerici, ecc.).
Il comportamento è spiegato nella sezione Valori generati della documentazione di EF Core:
Se si aggiunge un'entità al contesto che ha un valore assegnato alla proprietà, EF tenterà di inserire quel valore anziché generarne uno nuovo. Si considera che una proprietà abbia un valore assegnato se non viene assegnato il valore predefinito CLR (
null
perstring
,0
perint
,Guid.Empty
perGuid
, ecc.). Per ulteriori informazioni, vedere Valori espliciti per le proprietà generate .
Questo è fondamentalmente per consentire i cosiddetti scenari di "inserimento di identità" quando si caricano i dati. Per ulteriori informazioni, vedere Valori espliciti nelle colonne IDENTITY di SQL Server .
Detto questo, se non si desidera tale comportamento, assicurarsi che tutte le proprietà Id
(PK) dell'entità siano impostate su 0
prima di chiamare l'aggiunta dell'entità al contesto / set di database.
Ho risolto l'aggiunta di UseSqlServerIdentityColumn()
nella configurazione della proprietà Id:
builder.Property(k => k.Id)
.ValueGeneratedOnAdd()
.UseSqlServerIdentityColumn()
...
Si noti che fa parte di SqlServerPropertyBuilderExtensions
all'interno del pacchetto Microsoft.EntityFrameworkCore.SqlServer .
Nota .UseSqlServerIdentityColumn()
è stato deprecato e modificato in .UseIdentityColumn()
per "Microsoft.EntityFrameworkCore.SqlServer" versioni 3.xe (3.0 e 3.1 al momento della stesura di questo)