7.6 KiB
ex_042_005_Keys_data_annotations_
06/01/2020 ⋅ Marc Chevaldonné
Cet exemple traite des clés primaires associées aux entités.
Prérequis : je n'explique pas à travers cet exemple les principes de base d'Entity Framework Core et en particulier les chaînes de connexion et le lien entre entité et table. Pour plus de renseignements sur :
- les chaînes de connexion : ex_041_001_ConnectionStrings
- les liens entre entités et tables : ex_042_001_EF_CF_conventions, ex_042_002_EF_CF_data_annotations et ex_042_003_EF_CF_Fluent_API
Cet exemple montre le cas particulier de la gestion des clés primaires lors de l'utilisation des data annotations.
Vous pourrez trouver une version plus ou moins équivalente avec les conventions d'écriture ici : ex_042_004_Keys_conventions.
Vous pourrez trouver une version plus ou moins équivalente avec la Fluent API ici : ex_042_006_Keys_FluentAPI.
Les clés primaires
Une clé permet de rendre unique chaque instance d'une entité. La plupart des entités n'ont qu'une seule clé qui est alors transformée en clé primaire pour les bases de données relationnelles.
Note: une entité peut avoir d'autres clés, on parle d'alternate keys. Elles seront présentées dans les exemples sur les relations entre entités.
Si on utilise les data annotations, une propriété pour être transformée en clé doit respecter les contraintes suivantes :
- aucune contrainte sur le nommage de la propriété ; j'ai par exemple choisi
UniqueId
pourNounours
, etFrakId
pourCylon
. - elle doit être précédée de l'annotation
[Key]
- elle peut être générée par la base et dans ce cas elle doit être précédée de l'annotation
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
, ou ne pas être générée par la base et dans ce cas être précédée de l'annotation[DatabaseGenerated(DatabaseGeneratedOption.None)]
. Dans ce dernier cas, c'est à l'utilisateur de gérer ses propres clés et leur unicité dans la base. - elle peut être de différents types
int
,string
,Guid
,byte[]
... attention toutefois si vous choisissez de laisser la table générer les valeurs car certains fournisseurs ne savent pas générer tous les types.
La classe Nounours
La classe Nounours
utilise les data annotations et laisse le soin à la base de générer les clés uniques.
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UniqueId
{
get; set;
}
La classe Cylon
La classe Cylon
utilise les data annotations et laisse le soin à l'utilisateur de gérer ses clés uniques.
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int FrakId
{
get; set;
}
La classe Program
Cette classe est le point d'entrée du programme :
- Elle crée des instances de
Nounours
et deCylon
et les ajoute en base après avoir nettoyé les tables au préalables.
Notez que l'utilisateur n'a pas besoin de donner une valeur àNounours.UniqueId
puisque la base s'en charge, alors qu'il doit donner une valeur àCylon.FrakId
car la base de ne génère pas les clés.
Si vous ne donnez pas une valeur àCylon.FrakId
, alors la valeur par défaut est donnée (0
). Il n'y aura pas de problème si cet identifiant n'a pas été donné, mais dès le deuxièmeCylon
, vous aurez une exception.
*Note : la valeur par défaut pourint
est0
; pourGuid
,Guid.Empty
; pourstring
,null
... *
Nounours chewie = new Nounours { Nom = "Chewbacca", DateDeNaissance = new DateTime(1977, 5, 27), NbPoils = 1234567 };
Nounours yoda = new Nounours { Nom = "Yoda", DateDeNaissance = new DateTime(1980, 5, 21), NbPoils = 3 };
Nounours ewok = new Nounours { Nom = "Ewok", DateDeNaissance = new DateTime(1983, 5, 25), NbPoils = 3456789 };
Cylon c1 = new Cylon { FrakId = 2, Name = "John Cavil", Generation = 1 };
Cylon c2 = new Cylon { FrakId = 4, Name = "Leoben Conoy", Generation = 2 };
Cylon c3 = new Cylon { FrakId = 6, Name = "D'Anna Biers", Generation = 3 };
Cylon c4 = new Cylon { FrakId = 8, Name = "Simon", Generation = 4 };
Cylon c5 = new Cylon { FrakId = 10, Name = "Aaron Doral", Generation = 5 };
Cylon c6 = new Cylon { FrakId = 12, Name = "Caprica 6", Generation = 6 };
Cylon c7 = new Cylon { FrakId = 14, Name = "Daniel", Generation = 7 };
Cylon c8 = new Cylon { FrakId = 16, Name = "Boomer", Generation = 8 };
Cylon c9 = new Cylon { FrakId = 17, Name = "Athena", Generation = 8 };
- Elle affiche les
Nounours
et lesCylon
. Notez la génération des identifiants pour la classeNounours
uniquement : si vous exécutez plusieurs fois l'exemple, les clés desNounours
changent mais pas celles desCylon
.
Comment exécuter cet exemple ?
Pour tester cette application, n'oubliez pas les commandes comme présentées dans l'exemple ex_041_001 : pour générer l'exemple, il vous faut d'abord préparer les migrations et les tables.
- Ouvrez la Console du Gestionnaire de package, pour cela, dirigez-vous dans le menu Outils, puis Gestionnaire de package NuGet, puis Console du Gestionnaire de package.
- Dans la console que vous venez d'ouvrir, déplacez-vous dans le dossier du projet .NET Core, ici :
cd .\p08_BDD_EntityFramework\ex_042_005_Keys_data_annotations
Note: si vous n'avez pas installé correctement EntityFrameworkCore, il vous faudra peut-être utiliser également :
-
dotnet tool install --global dotnet-ef
si vous utilisez la dernière version de .NET Core (3.1 aujourd'hui), -
dotnet tool install --global dotnet-ef --version 3.0.0
si vous vous utiliser spécifiquement .NET Core 3.0.- Migration :
dotnet ef migrations add migration ex_042_005
- Création de la table :
dotnet ef database update
-
Génération et exécution Vous pouvez maintenant générer et exécuter l'exemple ex_042_005_Keys_data_annotations.
-
Comment vérifier le contenu des bases de données SQL Server ? Vous pouvez vérifier le contenu de votre base en utilisant l'Explorateur d'objets SQL Server.
-
Pour cela, allez dans le menu Affichage puis Explorateur d'objets SQL Server.
-
Déployez dans l'Explorateur d'objets SQL Server :
- SQL Server,
- puis (localdb)\MSSQLLocalDB ...,
- puis Bases de données
- puis celle portant le nom de votre migration, dans mon cas : ex_042_005_Keys_data_annotations.Nounours.mdf
- puis Tables
- Faites un clic droit sur la table dbo.Nounours puis choisissez Afficher les données
-
Le résultat de l'exécution peut être :
database after cleaning and adding 3 Nounours and 9 Cylons and saving changes :
Nounours 1: Chewbacca (27/05/1977, 1234567 poils)
Nounours 2: Yoda (21/05/1980, 3 poils)
Nounours 3: Ewok (25/05/1983, 3456789 poils)
Cylon 2: John Cavil, Number 1
Cylon 4: Leoben Conoy, Number 2
Cylon 6: D'Anna Biers, Number 3
Cylon 8: Simon, Number 4
Cylon 10: Aaron Doral, Number 5
Cylon 12: Caprica 6, Number 6
Cylon 14: Daniel, Number 7
Cylon 16: Boomer, Number 8
Cylon 17: Athena, Number 8
Note: les identifiants des Nounours
peuvent varier en fonction du nombre d'exécution de l'exemple depuis la création de la base de données, mais pas ceux des Cylon
puisqu'ils sont gérés par l'utilisateur.