web-dev-qa-db-fra.com

Incrémentation automatique sur une clé primaire partielle avec Entity Framework Core

J'ai déclaré le modèle suivant à l'aide de l'API EF Core fluent:

modelBuilder.Entity<Foo>()
    .HasKey(p => new { p.Name, p.Id });

Les deux champs sont marqués comme clé primaire lorsque je crée la base de données dans PostgreSQL, mais le champ Id n'est pas marqué comme incrémentation automatique. J'ai aussi essayé d'ajouter

[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]

dans le champ Id sous Foo sans que cela fasse une différence sur le code de migration. Y at-il un moyen de faire l'ID AI même s'il s'agit d'un PPK?

35
Martin

Eh bien, ces annotations de données devraient faire l'affaire, peut-être est-il lié au fournisseur PostgreSQL.

De documentation EF Core :

Selon le fournisseur de base de données utilisé, des valeurs peuvent être générées côté client par EF ou dans la base de données. Si la valeur est générée par la base de données, EF peut affecter une valeur temporaire lorsque vous ajoutez l'entité au contexte. Cette valeur temporaire sera alors remplacée par la valeur générée par la base de données au cours de SaveChanges.

Vous pouvez également essayer avec cette configuration Fluent Api:

modelBuilder.Entity<Foo>()
            .Property(f => f.Id)
            .ValueGeneratedOnAdd();

Mais comme je l’ai dit plus tôt, je pense que cela est lié au fournisseur de base de données. Essayez d’ajouter une nouvelle ligne à votre base de données et vérifiez ultérieurement si une valeur a été générée dans la colonne Id.

44
octavioccl

Tout d’abord, vous ne devriez pas fusionner l’API Fluent avec l’annotation des données, je vous suggère donc d’utiliser l’un des éléments suivants:

assurez-vous d'avoir correctement réglé les clés

modelBuilder.Entity<Foo>()
            .HasKey(p => new { p.Name, p.Id });
modelBuilder.Entity<Foo>().Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

OU vous pouvez le réaliser en utilisant aussi des annotations de données

public class Foo
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Key, Column(Order = 0)]
    public int Id { get; set; }

    [Key, Column(Order = 1)]
    public string Name{ get; set; }
}
12

À tous ceux qui rencontrent cette question et qui utilisent base de données SQL Server et ont toujours une exception levée même après avoir ajouté l'annotation suivante à la clé primaire int

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

Veuillez vérifier votre code SQL, assurez-vous que la clé primaire est identifiée par "IDENTITY (startValue, increment)",

CREATE TABLE [dbo].[User]
(
    [Id] INT IDENTITY(1,1) NOT NULL PRIMARY KEY
)

Cela fera en sorte que la base de données incrémente l'id à chaque fois qu'une nouvelle ligne est ajoutée, avec une valeur de départ de 1 et des incréments de 1.

J'ai accidentellement oublié cela dans mon SQL qui m'a coûté une heure de ma vie, alors j'espère que cela aide quelqu'un !!!

8
Saif Asad

Annoter la propriété comme ci-dessous

[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }

Pour utiliser les colonnes d'identité pour toutes les propriétés générées par des valeurs sur un nouveau modèle, placez simplement le texte suivant dans votre contexte OnModelCreating ():

builder.ForNpgsqlUseIdentityColumns();

Cela créera toutes les clés et autres propriétés qui ont .ValueGeneratedOnAdd () ont Identity par défaut. Vous pouvez utiliser ForNpgsqlUseIdentityAlwaysColumns () pour toujours avoir une identité. Vous pouvez également spécifier une identité propriété par propriété avec UseNpgsqlIdentityColumn () et UseNpgsqlIdentityAlwaysColumn ().

génération de valeur postgres efcore

4
Satheesh Davidson

Spécifier le type de colonne en série pour que PostgreSQL génère l'id.

[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column(Order=1, TypeName="serial")]
public int ID { get; set; }

https://www.postgresql.org/docs/current/static/datatype-numeric.html#DATATYPE-SERIAL

0
Naveen Verma