From 19a358e2f4643dc61579ca3c9cd59c5a27bf9b5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Chevaldonn=C3=A9?= Date: Fri, 17 Jan 2020 22:54:36 +0100 Subject: [PATCH] added ex_042_010_SinglePropertyNavigation_conventions; need to write the ReadMe file --- Exemples.sln | 26 ++++ .../Information.cs | 17 +++ .../Nounours.cs | 49 +++++++ .../NounoursDBEntities.cs | 14 ++ .../NounoursDBEntitiesWithStub.cs | 27 ++++ .../Program.cs | 45 +++++++ .../ReadMe.md | 122 ++++++++++++++++++ ...inglePropertyNavigation_conventions.csproj | 13 ++ 8 files changed, 313 insertions(+) create mode 100644 p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/Information.cs create mode 100644 p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/Nounours.cs create mode 100644 p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/NounoursDBEntities.cs create mode 100644 p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/NounoursDBEntitiesWithStub.cs create mode 100644 p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/Program.cs create mode 100644 p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/ReadMe.md create mode 100644 p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/ex_042_010_SinglePropertyNavigation_conventions.csproj diff --git a/Exemples.sln b/Exemples.sln index b9dda4e..e072a52 100644 --- a/Exemples.sln +++ b/Exemples.sln @@ -572,6 +572,11 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ex_042_009_DataSeeding", "p08_BDD_EntityFramework\ex_042_009_DataSeeding\ex_042_009_DataSeeding.csproj", "{B5CEC904-1475-4215-A20A-01BDD219AE25}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "04. Relationships", "04. Relationships", "{C7672736-AA73-4B7E-B5C6-A7A984216372}" + ProjectSection(SolutionItems) = preProject + p08_BDD_EntityFramework\Relationships.md = p08_BDD_EntityFramework\Relationships.md + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ex_042_010_SinglePropertyNavigation_conventions", "p08_BDD_EntityFramework\ex_042_010_SinglePropertyNavigation_conventions\ex_042_010_SinglePropertyNavigation_conventions.csproj", "{0D750BE3-0B5C-433C-A3A2-B70F390B4E93}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -4729,6 +4734,26 @@ Global {B5CEC904-1475-4215-A20A-01BDD219AE25}.Release|x64.Build.0 = Release|Any CPU {B5CEC904-1475-4215-A20A-01BDD219AE25}.Release|x86.ActiveCfg = Release|Any CPU {B5CEC904-1475-4215-A20A-01BDD219AE25}.Release|x86.Build.0 = Release|Any CPU + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93}.Debug|ARM.ActiveCfg = Debug|Any CPU + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93}.Debug|ARM.Build.0 = Debug|Any CPU + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93}.Debug|ARM64.Build.0 = Debug|Any CPU + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93}.Debug|x64.ActiveCfg = Debug|Any CPU + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93}.Debug|x64.Build.0 = Debug|Any CPU + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93}.Debug|x86.ActiveCfg = Debug|Any CPU + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93}.Debug|x86.Build.0 = Debug|Any CPU + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93}.Release|Any CPU.Build.0 = Release|Any CPU + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93}.Release|ARM.ActiveCfg = Release|Any CPU + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93}.Release|ARM.Build.0 = Release|Any CPU + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93}.Release|ARM64.ActiveCfg = Release|Any CPU + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93}.Release|ARM64.Build.0 = Release|Any CPU + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93}.Release|x64.ActiveCfg = Release|Any CPU + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93}.Release|x64.Build.0 = Release|Any CPU + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93}.Release|x86.ActiveCfg = Release|Any CPU + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -4999,6 +5024,7 @@ Global {2249C4B0-563D-44C8-AAA5-C8366A8F509C} = {56C5A51B-16E9-4F93-9C32-8F91710391E8} {B5CEC904-1475-4215-A20A-01BDD219AE25} = {78374D80-5BE7-425D-BE62-AD8F26491112} {C7672736-AA73-4B7E-B5C6-A7A984216372} = {55E00151-58A6-4E7D-9457-0BB8213B82F5} + {0D750BE3-0B5C-433C-A3A2-B70F390B4E93} = {C7672736-AA73-4B7E-B5C6-A7A984216372} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8D31C3AE-36FF-4667-A2A7-0E670245A59E} diff --git a/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/Information.cs b/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/Information.cs new file mode 100644 index 0000000..af73a75 --- /dev/null +++ b/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/Information.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Text; + +namespace ex_042_010_SinglePropertyNavigation_conventions +{ + public class Information + { + public int InformationId { get; set; } + + public string MadeBy { get; set; } + + public string MadeIn { get; set; } + } +} diff --git a/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/Nounours.cs b/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/Nounours.cs new file mode 100644 index 0000000..85ec878 --- /dev/null +++ b/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/Nounours.cs @@ -0,0 +1,49 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace ex_042_010_SinglePropertyNavigation_conventions +{ + public class Nounours + { + [Key] + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public Guid UniqueId + { + get; set; + } + + public string Nom + { + get; + set; + } + + [Column("Naissance", TypeName = "date")] + public DateTime DateDeNaissance + { + get; + set; + } + + public int NbPoils + { + get; + set; + } + + public Information Information + { + get; set; + } + + //public int InformationId + //{ get; set; } + + public override string ToString() + { + return $"{UniqueId}: {Nom} ({DateDeNaissance:dd/MM/yyyy}, {NbPoils} poils, fait à {Information.MadeIn} par {Information.MadeBy})"; + } + + } +} diff --git a/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/NounoursDBEntities.cs b/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/NounoursDBEntities.cs new file mode 100644 index 0000000..ef17ad4 --- /dev/null +++ b/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/NounoursDBEntities.cs @@ -0,0 +1,14 @@ +using Microsoft.EntityFrameworkCore; + +namespace ex_042_010_SinglePropertyNavigation_conventions +{ + class NounoursDBEntities : DbContext + { + public virtual DbSet NounoursSet { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseSqlite($"Data Source=ex_042_010_SinglePropertyNavigation_conventions.Nounours.db"); + } + } +} diff --git a/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/NounoursDBEntitiesWithStub.cs b/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/NounoursDBEntitiesWithStub.cs new file mode 100644 index 0000000..1bf3885 --- /dev/null +++ b/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/NounoursDBEntitiesWithStub.cs @@ -0,0 +1,27 @@ +using Microsoft.EntityFrameworkCore; +using System; + +namespace ex_042_010_SinglePropertyNavigation_conventions +{ + class NounoursDBEntitiesWithStub : NounoursDBEntities + { + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + var info1 = new Information { InformationId = 1, MadeBy = "George Lucas", MadeIn = "Kashyyyk" }; + var info2 = new Information { InformationId = 2, MadeBy = "George Lucas", MadeIn = "Dagobah" }; + var info3 = new Information { InformationId = 3, MadeBy = "George Lucas", MadeIn = "Lune forestière d'Endor" }; + + modelBuilder.Entity().HasData(info1, info2, info3); + + modelBuilder.Entity().Property("InformationId"); + + modelBuilder.Entity().HasData( + new { UniqueId = Guid.Parse("{4422C524-B2CB-43EF-8263-990C3CEA7CAE}"), Nom = "Chewbacca", DateDeNaissance = new DateTime(1977, 5, 27), NbPoils = 1234567, InformationId = 1 }, + new { UniqueId = Guid.Parse("{A4F84D92-C20F-4F2D-B3F9-CA00EF556E72}"), Nom = "Yoda", DateDeNaissance = new DateTime(1980, 5, 21), NbPoils = 3, InformationId = 2 }, + new { UniqueId = Guid.Parse("{AE5FE535-F041-445E-B570-28B75BC78CB9}"), Nom = "Ewok", DateDeNaissance = new DateTime(1983, 5, 25), NbPoils = 3456789, InformationId = 3 } + ); + } + } +} diff --git a/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/Program.cs b/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/Program.cs new file mode 100644 index 0000000..821eb15 --- /dev/null +++ b/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/Program.cs @@ -0,0 +1,45 @@ +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; +using System; +using System.Linq; +using static System.Console; + +namespace ex_042_010_SinglePropertyNavigation_conventions +{ + class Program + { + static void Main(string[] args) + { + OutputEncoding = System.Text.Encoding.UTF8; + + var info1 = new Information { MadeBy = "George Lucas", MadeIn = "Kashyyyk" }; + var info2 = new Information { MadeBy = "George Lucas", MadeIn = "Dagobah" }; + var info3 = new Information { MadeBy = "George Lucas", MadeIn = "Lune forestière d'Endor" }; + var n1 = new Nounours { Nom = "Chewbacca", DateDeNaissance = new DateTime(1977, 5, 27), NbPoils = 1234567, Information = info1 }; + var n2 = new Nounours { Nom = "Yoda", DateDeNaissance = new DateTime(1980, 5, 21), NbPoils = 3, Information = info2 }; + var n3 = new Nounours { Nom = "Ewok", DateDeNaissance = new DateTime(1983, 5, 25), NbPoils = 3456789, Information = info3 }; + + + + try + { + using (NounoursDBEntities db = new NounoursDBEntities()) + { + WriteLine("Contenu de la base :"); + foreach (var n in db.NounoursSet.Include(n => n.Information)) + { + WriteLine($"\t{n}"); + } + + } + } + catch (SqliteException) + { + WriteLine("Votre base de données n'existe pas. C'est peut-être la première fois que vous exécutez cet exemple."); + WriteLine("Pour créer la base de données, suivez les instructions données dans le fichier ReadMe.md associé à cet exemple."); + } + + ReadLine(); + } + } +} diff --git a/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/ReadMe.md b/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/ReadMe.md new file mode 100644 index 0000000..3c600bf --- /dev/null +++ b/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/ReadMe.md @@ -0,0 +1,122 @@ +# ex_042_010_SinglePropertyNavigation_conventions + +**TO BE WRITTEN** + + +*17/01/2020 ⋅ Marc Chevaldonné* + +--- + +Cet exemple montre comment réaliser une navigation entre deux entités avec une propriété simple (sens unique) avec Entity Framework Core. + +--- + +## Comment est construit cet exemple ? +* Le projet est de type .NET Core +* Il contient quatre classes : + * ```Nounours``` + * ```Information``` + * ```NounoursDBEntities``` + * ```NounoursDBEntitiesWithStub``` + +Le contenu des classes ```Nounours``` et ```NounoursDBEntities``` correspond à ce qui a été vu dans les exemples précédents. Seule la classe ```NounoursDBEntitiesWithStub``` sera donc expliquée ici. + +### La classe ```NounoursDBEntitiesWithStub``` + +* ```NounoursDBEntitiesWithStub``` est une classe fille de ```NounoursDBEntites```. +Son rôle est de proposer un Stub en plus de ce que sait déjà faire sa classe mère. Elle ne sera donc utilisée que pour des tests unitaires ou fonctionnels. +En conséquence, elle reprend tout ce que fait sa classe mère et ne change que la méthode ```OnModelCreating``` qui appelle la méthode de la classe mère puis ajoute des instances d'entités, grâce à la méthode d'extension ```HasData```. +```csharp +using Microsoft.EntityFrameworkCore; +using System; + +namespace ex_042_009_DataSeeding +{ + class NounoursDBEntitiesWithStub : NounoursDBEntities + { + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.Entity().HasData( + new Nounours { UniqueId = Guid.Parse("{4422C524-B2CB-43EF-8263-990C3CEA7CAE}"), Nom = "Chewbacca", DateDeNaissance = new DateTime(1977, 5, 27), NbPoils = 1234567 }, + new Nounours { UniqueId = Guid.Parse("{A4F84D92-C20F-4F2D-B3F9-CA00EF556E72}"), Nom = "Yoda", DateDeNaissance = new DateTime(1980, 5, 21), NbPoils = 3 }, + new Nounours { UniqueId = Guid.Parse("{AE5FE535-F041-445E-B570-28B75BC78CB9}"), Nom = "Ewok", DateDeNaissance = new DateTime(1983, 5, 25), NbPoils = 3456789 } + ); + } + } +} +``` +* __Note importante__ : remarquez que la création des instances d'entités donne aussi l'```UniqueId``` puisqu'il ne s'agit pas d'un ajout "classique" dans la base mais la table est créée avec ces instances. +* __Note importante__ : l'utilisation de ```UniqueId``` vous permettra d'ajouter des entités liées dans le Stub. +* __Explication__ : l'utilisaiton de ```HasData``` dans ```OnModelCreating``` fait que vos données stubbées feront parties de la migration : rien à voir avec un ajout depuis votre appli consommatrice. +* __Note__ : souvent, on en profite pour réécrire également ```OnConfiguring``` afin de changer de fournisseur (pour prendre par exemple un *SQLite in memory* puisque ce contexte stubbé est voué à être utilisé par des tests). + +* Elle est ensuite utilisée dans ```Program``` pour remplir la base de manière tout à fait classique et ne nécessite aucun appel supplémentaire. +```csharp +using (NounoursDBEntities db = new NounoursDBEntitiesWithStub()) +{ + WriteLine("Contenu de la base :"); + foreach (var n in db.NounoursSet) + { + WriteLine($"\t{n}"); + } +} +``` + +## 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_009_DataSeeding +``` + *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_009 +``` + * 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_009_DataSeeding**. + + * Le résultat de l'exécution va ressembler à : + ``` +Contenu de la base : + ae5fe535-f041-445e-b570-28b75bc78cb9: Ewok (25/05/1983, 3456789 poils) + 4422c524-b2cb-43ef-8263-990c3cea7cae: Chewbacca (27/05/1977, 1234567 poils) + a4f84d92-c20f-4f2d-b3f9-ca00ef556e72: Yoda (21/05/1980, 3 poils) +``` + + * 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_009_DataSeeding.Nounours.mdf* + * puis *Tables* + * Faites un clic droit sur la table *dbo.Nounours* puis choisissez *Afficher les données* + + + * Vous devriez maintenant pouvoir voir les données suivantes dans le tableau : + + |UniqueId |Nom|Naissance|NbPoils + |---|---|---|--- + |ae5fe535-f041-445e-b570-28b75bc78cb9|Ewok|25/05/1983|3456789 + |4422c524-b2cb-43ef-8263-990c3cea7cae|Chewbacca|27/05/1977|1234567 + |a4f84d92-c20f-4f2d-b3f9-ca00ef556e72|Yoda|21/05/1980|3 + diff --git a/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/ex_042_010_SinglePropertyNavigation_conventions.csproj b/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/ex_042_010_SinglePropertyNavigation_conventions.csproj new file mode 100644 index 0000000..6c2363d --- /dev/null +++ b/p08_BDD_EntityFramework/ex_042_010_SinglePropertyNavigation_conventions/ex_042_010_SinglePropertyNavigation_conventions.csproj @@ -0,0 +1,13 @@ + + + + Exe + netcoreapp3.0 + $(MSBuildProjectDirectory) + + + + + + +