parent
68c5221270
commit
1afbe0bc3f
@ -0,0 +1,128 @@
|
|||||||
|
# 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``` pour ```Nounours```, et ```FrakId``` pour ```Cylon```.
|
||||||
|
* 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.
|
||||||
|
```csharp
|
||||||
|
[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.
|
||||||
|
```csharp
|
||||||
|
[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 de ```Cylon``` 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ème ```Cylon```, vous aurez une exception.
|
||||||
|
*Note : la valeur par défaut pour ```int``` est ```0``` ; pour ```Guid```, ```Guid.Empty``` ; pour ```string```, ```null```... *
|
||||||
|
```csharp
|
||||||
|
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 les ```Cylon```.
|
||||||
|
*Notez la génération des identifiants pour la classe ```Nounours``` uniquement : si vous exécutez plusieurs fois l'exemple, les clés des ```Nounours``` changent mais pas celles des ```Cylon```.*
|
||||||
|
|
||||||
|
## 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```
|
||||||
|
|
||||||
|
* 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 et SQLite ?
|
||||||
|
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*.
|
||||||
|
<img src="../ex_041_001_ConnectionStrings/readmefiles/sqlserver_01.png" width="500"/>
|
||||||
|
|
||||||
|
* 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_004_Keys_conventions.Nounours.mdf*
|
||||||
|
* puis *Tables*
|
||||||
|
* Faites un clic droit sur la table *dbo.Nounours* puis choisissez *Afficher les données*
|
||||||
|
<img src="../ex_041_001_ConnectionStrings/readmefiles/sqlserver_02.png" width="460"/>
|
||||||
|
|
||||||
|
* 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.*
|
@ -0,0 +1,12 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.0" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.0" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.0"/>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
Loading…
Reference in new issue