---
sidebar_label: 'Introduction'
sidebar_position: 1
description: 'Start here'
---

# Entity Framework Core 3.0
*25/01/2020 &sdot; Marc Chevaldonné*  

---
Entity Framework (EF) Core est un ORM (Object-Relational Mapper) qui permet aux développeurs .NET de gérer de manière simple, légère et extensible, des bases de données.
EF permet de gérer de nombreux *providers* (SQL Server, SQLite, Cosmos, ...) de manière transparente.
EF vous permet également de mettre à jour vos bases de données et d'exécuter des requêtes sans avoir à écrire la moindre requête SQL. Vous pouvez passer par LINQ to SQL qui apportera plus de lisibilité et permettra au compilateur de vous aider à détecter vos erreurs.
  
---
:::note 
Différentes solutions existent avec EF pour gérer une base de données dont le modèle existe par exemple. Dans ces exemples, je ne traiterai que la partie *Code First*, c'est-à-dire le cas où le modèle est créé à partir de vos classes.
:::
---
## Plan
Les exemples sont organisés selon le plan suivant:  
1. [**Fundamentals** :](../category/1-fundamentals)  
Dans cette partie, je donnerai quelques notions pour se connecter à une base à l'aide de chaîne de connection (*connection strings*), comment utiliser des *providers de tests...*.
Il s'agira en conséquence d'exemples simples manquants d'explications sur certains points, car ils seront présentés plus tard.
   * [**1.1. Connection Strings**](../Entity-Framework/Fundamentals/ConnectionStrings) : montre comment utiliser une chaîne de connexion SQL Server ou SQLite.
   * [**1.2. Testing in memory**](../Entity-Framework/Fundamentals/TestingInMemory) : présente comment utiliser des fournisseurs en mémoire pour éviter la surchage de la création d'une base de données en particulier dans le cas de tests unitaires. Cet exemple est composé de 4 projets.
2. *Model* :  
Ce chapitre s'attardera sur le lien entre le modèle et la base de données. En effet, avec EF, l'accès aux données se fait via le modèle, c'est-à-dire l'ensemble de vos classes (qui seront reliées à des tables créées plus ou moins automatiquement)
 ainsi qu'un contexte (```DbContext```) qui représentera une session de connexion avec votre (ou vos) base(s) de données.
   Je présenterai en conséquence tout d'abord comment écrire des classes pour votre modèle, puis comment écrire les différentes relations classiques (aggrégation, *one to one*, *one to many*, *many to many*, mais aussi les dictionnaires), comment gérer les héritages entre classes du modèle dans la base de données, etc.
   * [**2.1. : conventions d'écriture**](../Entity-Framework/Model/EF_CF_namingConventions) : explique quelles sont les conventions d'écriture utilisées pour la transformation d'une entité en table.
   * [**2.2. : data annotations**](../Entity-Framework/Model/EF_CF_dataAnnotations) : explique comment utiliser les *data annotations* pour personnaliser la transformation d'une entité en table.
   * [**2.3. : Fluent API**](../Entity-Framework/Model/EF_CF_FluentAPI) : explique comment utiliser la *Fluent API* pour personnaliser la transformation d'une entité en table.
   * [**2.4. : Keys with conventions**](../Entity-Framework/Model/EF_CF_KeysConvention) : explique comment créer les clés primaires d'une entité lorsqu'on utilise les conventions d'écriture.
   * [**2.5. : Keys with data annotations**](../Entity-Framework/Model/EF_CF_KeysDataAnnotations) : explique comment créer les clés primaires d'une entité lorsqu'on utilise les *data annotations*.
   * [**2.6. : Keys with Fluent API**](../Entity-Framework/Model/EF_CF_Keys_FluentAPI) : explique comment créer les clés primaires d'une entité lorsqu'on utilise la *Fluent API*.
   * [**2.7. : Value Generation**](../Entity-Framework/Model/ValueGeneration) : explique comment faire générer des valeurs automatiquement lors de l'insertion ou de la mise à jour
   * [**2.8 : Data Seeding before Entity Framework 2.1**](../Entity-Framework/Model/DataSeedingBeforeEF2_1) : explique comment utiliser un stub (méthode qui était recommandée avant EF Core 2.1)
   * [**2.9 : Data Seeding**](../Entity-Framework/Model/DataSeeding) : explique comment utiliser un stub (méthode recommandée depuis EF Core 2.1)
   * [**Relationships**](Relationships.md) : en cliquant [ici](Relationships.md), vous aurez plus de détails sur les relations entre entités
     * [**ex_042_010 : Single Property navigation with data annotations**](ex_042_010_SinglePropertyNavigation_conventions) : montre comment une relation d'association est traduite par *EF Core* lorsque cette association est unidirectionnelle entre deux entités, en utilisant les conventions d'écriture et/ou les annotations de données. 
     * [**ex_042_011 : Single Property navigation with Fluent API**](ex_042_011_SinglePropertyNavigation_FluentAPI) : montre comment une relation d'association est traduite par *EF Core* lorsque cette association est unidirectionnelle entre deux entités, en utilisant la *FLuent API*. 
     * [**ex_042_012 : One To One with data annotations**](ex_042_012_OneToOne_conventions) : montre comment une relation d'association *One To One* est traduite par *EF Core* lorsque cette association est bidirectionnelle entre deux entités, en utilisant l'*annotation de données*. 
     * [**ex_042_013 : One To One with Fluent API**](ex_042_013_OneToOne_FluentAPI) : montre comment une relation d'association *One To One* est traduite par *EF Core* lorsque cette association est bidirectionnelle entre deux entités, en utilisant la *FluentAPI*. 
     * [**ex_042_014 : One To Many with data annotations**](ex_042_014_OneToMany_dataAnnotations) : montre comment une relation d'association *One To Many* est traduite par *EF Core* en utilisant l'*annotation de données*. 
     * [**ex_042_015 : One To Many with conventions**](ex_042_015_OneToMany_conventions) : montre comment une relation d'association *One To Many* est traduite par *EF Core* en utilisant les *conventions d'écriture*. 
     * [**ex_042_016 : One To Many with Fluent API**](ex_042_016_OneToMany_FluentAPI) : montre comment une relation d'association *One To Many* est traduite par *EF Core* en utilisant la *Fluent API*. 
1. *Schemas and migrations* :
   Le but de ce chapitre sera de vous montrer comment garder votre modèle et votre base de données synchronisés.
2. *Querying (LINQ to SQL) and saving data* :
   *Language INtegrated Query* (LINQ) est un outil de requête sur collections et sa version LINQ to SQL vous permet de passer très facilement à un système de requêtes sur les bases de données.
Les requêtes LINQ sont automatiquement traduites en requêtes SQL, vous évitant ainsi d'avoir à écrire vos requêtes vous-mêmes. Elles sont dès lors beaucoup plus lisibles et faciles à écrire.
Ce chapitre présente comment charger des données, réaliser du filtrage, de manière synchrone ou asynchrone, etc.
   Il montre bien sûr également comment réaliser le symétrique : mettre à jour, supprimer ou ajouter de nouvelles données dans la base.
5. *Database providers* :
   EF vous permet de gérer votre base de données indépendamment du *provider*. Ce chapitre montrera donc comment utiliser différents providers parmi lesquels Microsoft SQL Server, SQLite ou encore InMemory dont le but est de permettre de tester la base en mémoire, sans passer par un *provider*.
   
---

## Quelle version utiliser ?
Ces exemples sont écrits pour .NET Core 3.0, mais vous pouvez utiliser EF Core avec différents types projets. Voici les recommendations actuelles de Microsoft quant à l'utilisation des version d'EF.
   
|**EF Core**     |**1.x** |**2.x**    |**3.x**
|----------------|--------|-----------|---------------
|.NET Standard   |1.3     |2.0        |2.1
|.NET Core       |1.0     |2.0        |3.0
|.NET Framework  |4.5.1   |4.7.2      |(not supported)
|Mono            |4.6     |5.4        |6.4
|Xamarin.iOS     |10.0    |10.14      |12.16
|Xamarin.Android |7.0     |8.0        |10.0
|UWP             |10.0    |10.0.16299 |to be defined
|Unity           |2018.1  |2018.1     |to be defined

:::tip Comment lire ce tableau ?
   
Si vous voulez utiliser EF Core 3.0 avec une bibliothèque de classes écrites en .NET Standard, celle-ci doit utiliser au moins .NET Standard 2.1.
   
Si vous voulez utiliser EF Core 3.0 avec un projet Xamarin.iOS, celui-ci doit être au moins en version 12.16.
   
Si vous voulez utiliser EF Core dans une application UWP, vous ne pouvez pour le moment utiliser que EF Core 1.x ou 2.x.

:::

:::note
   
Je n'ai pas l'intention de mettre à jour les exemples pour Entity Framework 6 ou pour .NET Framework, puisque la version 5 du framework va unifier .NET Framework et .NET Core. En conséquence, EF Core sera la nouvelle "norme".

:::
    
---
## Comment commencer ?
Un petit tutoriel rapide pour savoir comment créer un projet...
##### Prérequis
Il vous faut au moins la **[version 3.0 du SDK de .NET Core](https://dotnet.microsoft.com/download)**, mais celle-ci est certainement déjà installée si vous avez installé Visual Studio 2019 16.3 ou plus.
##### Créez un nouveau projet
Vous pouvez ensuite créer un nouveau projet .NET Core 3.x, pour cela :
* lancez Visual Studio
* créez un nouveau projet de type **Console App (.NET Core)** en C#

##### Installez EntityFramework Core
Pour ce tutoriel, nous pouvons utiliser SqlServer comme *provider*.
* Pour cela, cliquez droit sur le projet, puis sélectionnez *Gérer les packages NuGet...*.
* Sous l'onglet *Parcourir*, dans la barre de recherche, rentrez *Microsoft.EntityFrameworkCore*
* Sélectionnez le premier nuget dans sa version la plus récente et lancez l'installation.
* Répétez les deux dernières opérations pour les packages :
  * *Microsoft.EntityFrameworkCore.Design*
  * *Microsoft.EntityFrameworkCore.SqlServer*
  * *Microsoft.EntityFrameworkCore.SqlServer.Design*

##### Créez un modèle
* Ajoutez une nouvelle classe ```Nounours``` au projet.
* Ajoutez le code suivant à cette classe :

```csharp title='Nounours.cs'
using System;

namespace tutoRapideEFCore
{
    class Nounours
    {
        public int Id { get; set; }
        public string Nom { get; set; }
        public DateTime Naissance { get; set; }
        public int NbPoils { get; set; }
    }
}
```

* Ajoutez une nouvelle classe ```NounoursContext``` qui servira de contexte à notre modèle.
* Ajoutez le code suivante à cette classe :

```csharp title="NounoursContext.cs"
using Microsoft.EntityFrameworkCore;

namespace tutoRapideEFCore
{
    class NounoursContext : DbContext
    {
        public DbSet<Nounours> Nounours { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder options)
            => options.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=myFirstDatabase.mdf;Trusted_Connection=True;");
    }
}

```
##### Créez la base de données
* 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 (*eg* si votre projet s'apelle **tutoRapideEFCore**) :
```
cd tutoRapideEFCore
```
* tapez ensuite les commandes suivantes :
```
dotnet ef migrations add myFirstMigration
dotnet ef database update 
```

:::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.
:::

##### Utilisez votre base de données via Entity Framework Core
* Editez *Program.cs* et ajoutez le code suivant :
```csharp title="Program.cs"
static void Main(string[] args)
{
    Nounours chewie = new Nounours { Nom = "Chewbacca", Naissance = new DateTime(1977, 5, 27), NbPoils = 1234567 };
    Nounours yoda = new Nounours { Nom = "Yoda", Naissance = new DateTime(1980, 5, 21), NbPoils = 3 };
    Nounours ewok = new Nounours { Nom = "Ewok", Naissance = new DateTime(1983, 5, 25), NbPoils = 3456789 };
    Nounours c3po = new Nounours { Nom = "C3PO", Naissance = new DateTime(1977, 5, 27), NbPoils = 0 };

    using (var context = new NounoursContext())
    {
        // Crée des nounours et les insère dans la base
        Console.WriteLine("Creates and inserts new Nounours");
        context.Add(chewie);
        context.Add(yoda);
        context.Add(ewok);
        context.Add(c3po);
        context.SaveChanges();
    }
}
```
Maintenant, lorsque vous lancerez l'application, la base de données contiendra 3 nounours. La base crée automatiquement des identifiants pour chaque Nounours.
* Editez *Program.cs* pour rajouter les lignes suivantes à la fin de la méthode ```Main``` :
```csharp title="Program.cs"
// Lit le premier nounours de la base dont le nom commence par 'e'
Console.WriteLine("Creates and executes a query retrieving the first Nounours of the database whose name starts with an \"e\":");
var eNounours = context.Nounours
    .Where(n => n.Nom.StartsWith("e"))
    .First();
Console.WriteLine($"{eNounours.Nom} (born in {eNounours.Naissance.Year})");
```
Cette requête LINQ vous permet de lire le premier nounours de la base de nounours triés par ordre alphabétique de noms.  
Ceci nécessite de rajouter au-début du fichier *Program.cs* la ligne suivante :  
```csharp title="Program.cs"
using System.Linq;
```
* Editez *Program.cs* pour rajouter les lignes suivantes à la fin de la méthode ```Main``` :
```csharp title="Program.cs"
// Met à jour le nom du second nounours de la base
Console.WriteLine("Updates the name of the second nounours");
eNounours.Nom = "Wicket";
context.SaveChanges();
```
Cette partie du code montre comment mettre à jour un élément de la base de données.
* Editez *Program.cs* pour rajouter les lignes suivantes à la fin de la méthode ```Main``` :
```csharp title="Program.cs"
// récupère le nounours qui n'en est pas un et le supprime de la base
Console.WriteLine("Deletes one item from de database");
var droid = context.Nounours
    .SingleOrDefault(n => n.Nom.Equals("C3PO"));
context.Remove(droid);
context.SaveChanges();
```
Cette partie du code montre comment supprimer un élément de la base de données.   
   
Voici un récapitulatif du fichier *Program.cs* :
```csharp title="Program.cs"
using System;
using System.Linq;

namespace tutoRapideEFCore
{
    class Program
    {
        static void Main(string[] args)
        {
            Nounours chewie = new Nounours { Nom = "Chewbacca", Naissance = new DateTime(1977, 5, 27), NbPoils = 1234567 };
            Nounours yoda = new Nounours { Nom = "Yoda", Naissance = new DateTime(1980, 5, 21), NbPoils = 3 };
            Nounours ewok = new Nounours { Nom = "Ewok", Naissance = new DateTime(1983, 5, 25), NbPoils = 3456789 };
            Nounours c3po = new Nounours { Nom = "C3PO", Naissance = new DateTime(1977, 5, 27), NbPoils = 0 };

            using (var context = new NounoursContext())
            {
                // Crée des nounours et les insère dans la base
                Console.WriteLine("Creates and inserts new Nounours");
                context.Add(chewie);
                context.Add(yoda);
                context.Add(ewok);
                context.Add(c3po);
                context.SaveChanges();

                // Lit le premier nounours de la base dont le nom commence par 'e'
                Console.WriteLine("Creates and executes a query retrieving the first Nounours of the database whose name starts with an \"e\":");
                var eNounours = context.Nounours
                    .Where(n => n.Nom.StartsWith("e"))
                    .First();
                Console.WriteLine($"{eNounours.Nom} (born in {eNounours.Naissance.Year})");

                // Met à jour le nom du second nounours de la base
                Console.WriteLine("Updates the name of the second nounours");
                eNounours.Nom = "Wicket";
                context.SaveChanges();

                // récupère le nounours qui n'en est pas un et le supprime de la base
                Console.WriteLine("Deletes one item from de database");
                var droid = context.Nounours
                    .SingleOrDefault(n => n.Nom.Equals("C3PO"));
                context.Remove(droid);
                context.SaveChanges();
            }
        }
    }
}
```
* Exécutez votre application pour vérifier son bon fonctionnement.

##### Vérifiez le contenu de la base de données avec l'Explorateur d'objets 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 : *myFirstDatabase.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 :  
 
  |Id   |Nom  |Naissance |NbPoils
  |---|---|---|---
  |1|Chewbacca|27/05/1977 00:00:00|1234567
  |2|Yoda|21/05/1980 00:00:00|3
  |3|Wicket|25/05/1983 00:00:00|3456789

Vous pouvez constater que l'Ewok a bien été renommé Wicket, et que C3PO a bien été supprimé.  
Notez qu'il est également possible d'utiliser l'*Explorateur d'objets SQL Server* pour ajouter, modifier ou supprimer des données dans les tables.