Saisie manuelle de clés avec Entity Framework

asp.net c# entity-framework entity-framework-core sql

Question

J'essaie d'abord d'utiliser le code Entity Framework pour un projet de base de données simple et je rencontre un problème que je n'arrive tout simplement pas à résoudre.

J'ai remarqué que EF configurait automatiquement l'ID de mes tables, augmentant de 1 à chaque fois, ignorant complètement la valeur entrée manuellement pour ce champ. Après quelques recherches, je crois comprendre que la bonne façon de désactiver ce comportement consiste à procéder comme suit:

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

Cependant maintenant je reçois juste cette erreur et je ne sais pas pourquoi:

Exception non gérée: System.Data.Entity.Infrastructure.DbUpdateException: une erreur s'est produite lors de la mise à jour des entrées. Voir l'exception interne pour plus de détails. ---

System.Data.UpdateException: une erreur s'est produite lors de la mise à jour des entrées. Voir l'exception interne pour plus de détails. ---> System.Data.SqlClient.SqlException: impossible d'insérer une valeur explicite pour la colonne d'identité dans la table 'Evénements' lorsque IDENTITY_INSERT est défini sur OFF.

Si cela vous aide, voici la classe POCO en question:

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<Match> Matches { get; set; }
    public virtual ICollection<EventParticipation> EventParticipation { get; set; }
}

Merci d'avance.

Réponse acceptée

Par défaut, Entity Framework suppose qu'une base primaire entière est générée par la base de données (ce qui revient à ajouter l'attribut HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity) ou l'appelant Property(e => e.EventID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); dans l'API Fluent.

Si vous regardez la migration qui crée la table, vous devriez voir ceci:

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

Ensuite, vous avez modifié le modèle à l'aide de l'API Fluent en DatabaseGenerated.None . EF met cela dans la migration:

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

Et le sql généré est ceci:

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

Ce qui effectivement ne squatte pas. Supprimer l’IDENTITÉ d’une colonne n’est pas une mince affaire. Vous devez supprimer et recréer la table ou créer une nouvelle colonne, puis copier les données et corriger les clés étrangères. Il n’est donc pas surprenant que EF ne le fasse pas pour vous.

Vous devez trouver le meilleur moyen de le faire vous-même. Vous pouvez rétablir vos migrations sur 0 et ré-échafauder à partir de maintenant, après avoir spécifié DatabaseGeneratedOption.None , ou modifier manuellement la migration pour supprimer et recréer la table.

Ou vous pouvez supprimer et recréer la colonne:

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

EDIT Ou vous pouvez activer / désactiver l'identité avec une opération de migration personnalisée


Réponse populaire

Puisque je préfère les attributs, voici l’alternative par souci de complétude:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }

Remarque: cela fonctionne également dans EF Core.



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi