Inserimento manuale delle chiavi con Entity Framework

Sto provando a utilizzare il codice Entity Framework per un semplice progetto di database e mi imbatto in un problema che non riesco a capire.

Ho notato che EF stava impostando l’ID dei miei tavoli automaticamente aumentando di 1 ogni volta, ignorando completamente il valore inserito manualmente per quel campo. Dopo alcune ricerche, ho capito che il modo giusto per disabilitare questo comportamento è:

modelBuilder.Entity().Property(e => e.EventID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 

Comunque ora sto ricevendo questo errore e non ho idea del perché:

Eccezione non gestita: System.Data.Entity.Infrastructure.DbUpdateException: si è verificato un errore durante l’aggiornamento delle voci. Vedi l’eccezione interna per i dettagli. —

System.Data.UpdateException: si è verificato un errore durante l’aggiornamento delle voci. Vedi l’eccezione interna per i dettagli. —> System.Data.SqlClient.SqlException: imansible inserire il valore esplicito per la colonna Identity nella tabella “Events” quando IDENTITY_INSERT è impostato su OFF.

Se è utile, ecco la class POCO in questione:

 public class Event { [Key, Required] public int EventID { get; set; } public string EventType { get; set; } //TODO: Event Type Table later on public DateTime StartDate { get; set; } public DateTime EndDate { get; set; } public virtual ICollection Matches { get; set; } public virtual ICollection EventParticipation { get; set; } } 

Grazie in anticipo.

Per impostazione predefinita, Entity Framework presuppone che una chiave primaria intera sia generata dal database (equivalente all’aggiunta di HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity) o alla chiamata Property(e => e.EventID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); in Fluent API.

Se osservi la migrazione che crea la tabella dovresti vedere questo:

  CreateTable( "dbo.Events", c => new { EventID = c.Int(nullable: false, identity: true), //etc }) .PrimaryKey(t => t.EventID ); 

Quindi è stato modificato il modello utilizzando l’API Fluent in DatabaseGenerated.None . EF lo inserisce nella migrazione:

 AlterColumn("dbo.Events", "EventID", c => c.Int(nullable: false, identity: false)) 

E lo sql generato è questo:

ALTER TABLE [dbo].[Events] ALTER COLUMN [EventID] [int] NOT NULL

Che in realtà fa accovacciarsi. Eliminare l’IDENTITÀ da una colonna non è banale. È necessario eliminare e ricreare la tabella o creare una nuova colonna, quindi è necessario copiare i dati e correggere le chiavi esterne. Quindi non è sorprendente che EF non lo stia facendo per te.

Devi trovare il modo migliore per farlo da solo. È ansible ripristinare le migrazioni su 0 e re-impalcature da zero ora che è stato specificato DatabaseGeneratedOption.None oppure è ansible modificare manualmente la migrazione per eliminare e ricreare la tabella.

Oppure puoi rilasciare e ricreare la colonna:

 DropColumn("Customer", "CustomerId"); AddColumn("Customer", "CustomerId", c => c.Long(nullable: false, identity: false)); 

MODIFICA O è ansible triggersre / distriggersre l’id quadro con un’operazione di migrazione personalizzata

Dal momento che preferisco gli attributi, qui l’alternativa per motivi di completezza:

 using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; [Key] [DatabaseGenerated(DatabaseGeneratedOption.None)] public int Id { get; set; }