IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Apprendre à exploiter le CLI d'EF Core - Partie 1 : les possibilités offertes par EF Core Migrations
Par Hinault Romaric

Le , par Hinault Romaric

0PARTAGES

Les développeurs d’Entity Framework Core ont publié il y a quelques semaines, la version 2.0 de l’ORM .NET, qui s’aligne avec les sorties de .NET Core 2.0 et ASP.NET Core 2.0.


Entity Framework Core est une re-implémentation du célèbre ORM sur de nouvelles bases, dont la performance et la souplesse. Il est encore dépourvu de nombreuses fonctionnalités d’Entity Framework 6, mais jusqu’ici, je suis assez satisfait de ce qui est offert.

EF Core s’arrime avec .NET Core et s’appuie sur ce dernier pour offrir des outils en ligne de commande permettant d’automatiser des nombreuses tâches comme la génération de code, ou encore la migration.

Le CLI d’EF Core est indépendant de tout environnement de développement, est cross-platform et peut être utilisé pour toute application .NET Core. De ce fait, il offre la même expérience aux utilisateurs sur Windows, OS X et Linux.

Le CLI offre une alternative à l’utilisation des commandes PowerShell avec la « Console du gestionnaire de package » de Visual Studio. Il s’agit de l’approche offerte par la version initiale de l’ORM (Entity Framework depuis la version 4.3) et qui est liée à l’IDE Visual Studio. EF Core a maintenu la prise en charge de PowerShell, en offrant une expérience similaire à EF 6.

Dans cette nouvelle série de billets, nous verrons quelques commandes qui peuvent grandement nous faciliter la vie et augmenter notre productivité en évitant de faire certaines choses manuellement.

Pour ce premier billet, nous verrons comment utiliser l’approche Code First et la migration pour créer une base de données à partir d’un modèle, mettre à jour cette dernière, annuler une mise à jour, etc.

Pourquoi EF Core Migrations

L’approche adoptée par les ORM permet de maintenir une certaine similitude entre le schéma de la base de données et le modèle de données de votre application. En phase de développement, le modèle de données est amené à changer fréquemment. Le schéma de la base de données doit donc suivre ces changements. Avec les premières versions d’Entity Framework Code Firts, toute modification apportée au modèle de données entrainait la destruction et la création à nouveau de la base de données. Ce qui a comme conséquence directe la perte des données. Une situation pouvant être tolérée pour une application qui n’est pas encore entrée en production.

Pour permettre aux développeurs d’appliquer avec souplesse les modifications apportées au modèle de données à la base de données, sans risque de perte de données, Entity Framework Core offre les Migrations.

Création de l’application d'exemple et intégration d’Entity Framework Core

Pour commencer, vous allez créer une application console en utilisant la commande suivante.

Code : Sélectionner tout
Dotnet new console -n DemoMigrations
Vous allez éditer le fichier DemoMigrations.csproj, avec n’importe quel éditeur de votre choix, et ajouter les références pour Entity Framework Core.

Code xml : Sélectionner tout
1
2
3
4
<ItemGroup> 
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.0" /> 
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqLite" Version="2.0.0" /> 
  </ItemGroup>

Positionnez-vous dans le dossier racine de l’application et exécutez la commande :

Code : Sélectionner tout
Dotnet restore
Dans le dossier racine de cette application, vous allez créer un dossier Models, ensuite dans celui-ci le fichier ToDo.cs, avec le code suivant :

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System; 
using System.ComponentModel.DataAnnotations; 
  
namespace DemoMigrations.Models 
{ 
   public class ToDo 
   { 
    public int Id { get; set; } 
  
    [Required] 
    public string Description { get; set; } 
  
     [Required] 
    public DateTime CreatedDate { get; set; } 
  
   } 
  
}

Par la suite, vous allez créer dans le même dossier la classe MigrationsContext, avec le code suivant :

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System; 
using Microsoft.EntityFrameworkCore; 
  
namespace DemoMigrations.Models 
{ 
public class MigrationsContext : DbContext 
{ 
    public MigrationsContext(DbContextOptions<MigrationsContext> options) 
            : base(options) 
    { 
  
    } 
    public DbSet<ToDo> ToDo { get; set; } 
} 
  
}

Enfin, vous allez ajouter dans le même dossier le fichier MigrationsContextFactory.cs, avec une classe qui implémente l’interface IDesignTimeDbContextFactory. Cette fabrique va être utilisée par les outils EF pour créer une instance de votre DBContext. Le code de ce fichier est le suivant :

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System; 
using Microsoft.EntityFrameworkCore.Design; 
using Microsoft.EntityFrameworkCore; 
using Microsoft.Extensions.Configuration; 
  
namespace DemoMigrations.Models 
{ 
public class MigrationsContextFactory : IDesignTimeDbContextFactory<MigrationsContext> 
{ 
        public MigrationsContext CreateDbContext(string[] args) 
        { 
            var builder = new DbContextOptionsBuilder<MigrationsContext>(); 
            builder.UseSqlite("Data Source=todo.db"); 
            return new MigrationsContext(builder.Options); 
  
      } 
} 
}

Configuration de la migration

L’utilisation des commandes de migrations nécessite l’intégration dans notre application du package Microsoft.EntityFrameworkCore.Tools.DotNet . Ce dernier doit être ajouté en paramètre dans la balise DotNetCliToolReference. Actuellement, il n’est pas possible de le faire en utilisant la commande dotnet add package. Vous allez donc le faire manuellement en éditant le ficher .csproj et en y ajoutant le code suivant :

Code xml : Sélectionner tout
1
2
3
<ItemGroup> 
  <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" /> 
</ItemGroup>

Le code complet du fichier .csproj devrait ressembler à ceci :

Code xml : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<Project Sdk="Microsoft.NET.Sdk"> 
  <PropertyGroup> 
    <OutputType>Exe</OutputType> 
    <TargetFramework>netcoreapp2.0</TargetFramework> 
  </PropertyGroup> 
  <ItemGroup> 
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.0" /> 
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqLite" Version="2.0.0" /> 
  </ItemGroup> 
  
  <ItemGroup> 
  <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" /> 
</ItemGroup> 
</Project>

Utilisez la commande dotnet restore pour restaurer les packages, ensuite dotnet build pour générer l’application et s’assurer que tout est correct.

Vous allez ensuite exécuter la commande dotnet ef -h, pour vérifier que le CLI Entity Framework est désormais supporté.


Vous êtes désormais prêt à exploiter les fonctionnalités de migrations offertes par Entity Framework pour votre application.

Création d’une migration

Pour créer une migration vous devez utiliser la commande dotnet ef migrations add [nom de la migration]. Pour créer donc notre première migration, nous allons utiliser la commande suivante, dans le dossier racine de l’application :

Code : Sélectionner tout
dotnet ef migrations add Initial
Un dossier Migrations sera créé à la racine de votre application, avec les fichiers suivants, contenant du code :


Le code de Migration est généré en faisant une comparaison entre le schéma de votre base de données et le modèle de données de votre application. Lorsque la base de données n’existe pas encore, le modèle de données est utilisé comme schéma initial de la base de données.

Les modifications apportées à votre modèle de données et qui doivent être appliquées à la base de données vont se traduire en du code qui sera disponible dans la méthode Up, de la classe portant le même nom que vous avez spécifié pour la migration. La méthode Down de cette classe permet d’annuler une migration et ramener la base de données à son état initial. Cette classe est contenue dans le fichier 20171014155614_Initial.cs.

Le code de la classe Initial pour notre application est le suivant :

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using Microsoft.EntityFrameworkCore.Migrations; 
using System; 
using System.Collections.Generic; 
  
namespace DemoMigrations.Migrations 
{ 
    public partial class Initial : Migration 
    { 
        protected override void Up(MigrationBuilder migrationBuilder) 
        { 
            migrationBuilder.CreateTable( 
                name: "ToDo", 
                columns: table => new 
                { 
                    Id = table.Column<int>(type: "INTEGER", nullable: false) 
                        .Annotation("Sqlite:Autoincrement", true), 
                    CreatedDate = table.Column<DateTime>(type: "TEXT", nullable: false), 
                    Description = table.Column<string>(type: "TEXT", nullable: false) 
                }, 
                constraints: table => 
                { 
                    table.PrimaryKey("PK_ToDo", x => x.Id); 
                }); 
        } 
  
        protected override void Down(MigrationBuilder migrationBuilder) 
        { 
            migrationBuilder.DropTable( 
                name: "ToDo"); 
        } 
    } 
}

Comme vous pouvez le constater, la méthode Up() permet de créer la table ToDo dans notre base de données et la méthode Down() permet de supprimer cette dernière.

Le fichier MigrationsContextModelSnapshot.cs est utilisé pour conserver en tout moment le schéma de la base de données. Ainsi, pour identifier les différences entre la base de données et le modèle de données, Ef Core Migrations n’a pas besoin de communiquer avec la base de données. L’interaction avec la base de données se fait uniquement lors de l’application de la migration.

Le code de cette classe ressemble à ceci :

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// <auto-generated /> 
using DemoMigrations.Models; 
using Microsoft.EntityFrameworkCore; 
using Microsoft.EntityFrameworkCore.Infrastructure; 
using Microsoft.EntityFrameworkCore.Metadata; 
using Microsoft.EntityFrameworkCore.Migrations; 
using Microsoft.EntityFrameworkCore.Storage; 
using Microsoft.EntityFrameworkCore.Storage.Internal; 
using System; 
  
namespace DemoMigrations.Migrations 
{ 
    [DbContext(typeof(MigrationsContext))] 
    partial class MigrationsContextModelSnapshot : ModelSnapshot 
    { 
        protected override void BuildModel(ModelBuilder modelBuilder) 
        { 
#pragma warning disable 612, 618 
            modelBuilder 
                .HasAnnotation("ProductVersion", "2.0.0-rtm-26452"); 
  
            modelBuilder.Entity("DemoMigrations.Models.ToDo", b => 
                { 
                    b.Property<int>("Id") 
                        .ValueGeneratedOnAdd(); 
  
                    b.Property<DateTime>("CreatedDate"); 
  
                    b.Property<string>("Description") 
                        .IsRequired(); 
  
                    b.HasKey("Id"); 
  
                    b.ToTable("ToDo"); 
                }); 
#pragma warning restore 612, 618 
        } 
    } 
}

Appliquer une Migration

Pour appliquer une migration, vous devez exécuter la commande :

Code : Sélectionner tout
Dotnet ef database update

Cette commande va exécuter la méthode Up de la classe Initial. S’il y’avait d’autres Migrations en attentes, elles seraient appliquées au même moment. Puisque la base de données n’existe pas encore, elle sera créée avec la table ToDo. Vous allez remarquer dans le dossier de votre application la présence d’un fichier todo.db.


Une table __EFMigrationsHistory est également ajoutée à cette base de données. Cette dernière va permettre de tracer les migrations qui ont été appliquées à la base de données. Actuellement, elle contient un seul enregistrement, celui de notre première migration.

Supprimer une migration

La suppression d’une migration se fait en utilisant la commande suivante :

Code : Sélectionner tout
dotnet ef migrations remove
Lorsque vous exécutez cette commande, les fichiers qui ont été créés pour la migration seront supprimés et le fichier ModelSnapshot reviendra à son état initial, pour représenter l’état de la base de données avant la création de cette migration.

Il faut noter que cette commande s’applique uniquement sur les migrations qui n’ont pas encore été appliquées à la base de données. Si aucune migration non appliquée n'existe, elle affichera le message d’erreur suivant :


Vous devez éviter de supprimer une migration en supprimant les fichiers qui ont été générés. Utilisez la commande réservée à cet effet.

Annuler une Migration

Avant de mettre en pratique l’annulation de la Migration, nous allons dans un premier temps appliquer une modification à notre base de données.

Vous allez éditer le fichier ToDo.cs et ajouter la nouvelle propriété Done :

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
public class ToDo 
   { 
    public int Id { get; set; } 
  
    [Required] 
    public string Description { get; set; } 
  
     [Required] 
    public DateTime CreatedDate { get; set; } 
  
    public Boolean Done {get; set;} 
   }

Ensuite créer et appliquer une nouvelle migration :

Code : Sélectionner tout
1
2
3
dotnet ef Migrations add  UpdateToDo 
 
dotnet ef database update
Maintenant nous allons annuler cette migration en exécutant la commande dotnet ef database update suivi du nom de la migration qui sera utilisé comme point de restauration. Dans notre cas, on veut ramener la base de données à l’état de la migration Initial. Vous devez donc exécuter la commande suivante :

Code : Sélectionner tout
dotnet ef database update Initial
Malheureusement, Entity Framework Core ne supporte pas la suppression d’une colonne en utilisant la migration. Je m’en suis rendu compte à la dernière minute, et c’est documenté ici : https://github.com/aspnet/EntityFram...ore/issues/329.

L’annulation d’une migration va entraîner l’exécution de la méthode Down. L’entrée dans la table __EFMigrationsHistory sera supprimée pour cette migration. C’est à la suppression de la migration en utilisant la commande correspondante que les fichiers de migration générés seront supprimés et le fichier ModelSnapshot reviendra dans l’état précédent.

C’est tout pour aujourd’hui. Vous avez désormais les outils pour appliquer avec souplesse les évolutions de modèle de données à votre base de données avec EF Core Migrations. Dans le prochain billet, nous verrons comment générer le modèle de données et le DbContext à partir d’une base de données.

Restez connecté !

Une erreur dans cette actualité ? Signalez-nous-la !