Créer une base de données à partir d’un contexte migré de EF6 à EF Core

Si l’on suit à la lettre le processus de conversion d’un contexte Entity Framework 6 (EF 6) existant vers Entity Framework Core (EF Core), la création d’une nouvelle base de données est impossible.

Petit rappel de la documentation :

Existing migrations

There isn't really a feasible way to port existing EF6 migrations to EF Core.

If possible, it is best to assume that all previous migrations from EF6 have been applied to the database and then start migrating the schema from that point using EF Core. To do this, you would use the Add-Migration command to add a migration once the model is ported to EF Core. You would then remove all code from the Up and Down methods of the scaffolded migration. Subsequent migrations will compare to the model when that initial migration was scaffolded.

Source : https://docs.microsoft.com/en-us/ef/efcore-and-ef6/porting/port-code

Dans le cas d’une nouvelle base de données :

  • Les méthodes Up et Down de votre première migration étant vide, EF ne créera pas les tables.

Dans le cas d’une base de données existante :

  • Si Up et Down sont vides, tout va bien. Si vous laissez le code de ces méthodes UP et Down par défaut, EF tentera de les créer, même sur une base existante.

Votre projet ne peut donc pas être utilisé pour ces deux cas.

Comment s’en sortir ?

Heureusement il existe une solution pour créer une migration qui peut répondre aux deux exigences en même temps. Pour cela, il faut regarder de près les options de la classe MigrationBuilder qui est passée en argument des méthodes Up et Down de nos migrations :

  • MigrationBuilder n’inclut pas de méthode pour tester l’existence de tables. (Zut, cela aurait été bien pratique).
  • MigrationBuilder dispose d’une méthode qui est en mesure de lancer des commandes SQL (vous voyez déjà où je veux en venir ?).
  • MigrationBuilder permet d’identifier le SGBD utilisé (pratique si on veut utiliser des commandes SQL propres à un SGBD ou un autre).

SQL sait créer des tables quand elle n’existe pas. On peut s’appuyer sur lui pour faire notre migration.

Pour cela, il suffit de connaitre la structure SQL de ses tables, et la syntaxe SQL propre à son SGBD.

Exemple : dans ce cas, j’utilise SQL Server pour créer une table Categories si elle n’existe pas.


public partial class Initialization : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.Sql(@"IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='Categories' AND xtype='U')
            BEGIN
            CREATE TABLE [Categories] (
            [Id]   INT           IDENTITY (1, 1) NOT NULL,
            [Name] NVARCHAR (40) NULL,
            CONSTRAINT [PK_dbo.Categories] PRIMARY KEY CLUSTERED ([Id] ASC))
            END");
    }
    
    protected override void Down(MigrationBuilder migrationBuilder){}
}

Bien entendu, il faudra procéder ainsi pour toutes les tables de votre modèle. Ce travail peut sembler laborieux, mais il n’en est rien. J’ai déjà utilisé cette approche pour deux projets sans le moindre problème.

Conclusion

C’est dans les vieux pots que l’on fait les meilleures soupes. Vous pensiez vraiment qu’en 2019 on créerait des bases de données sans le moindre code SQL ;)

Jérémy Jeanson

Comments

You have to be logged in to comment this post.