Dans notre projet asp.net core, nous souhaitons bénéficier des Migrations proposées par dotnet core. Or, nous avons un projet bien architecturé.
Comment réussir à en profiter sans tout casser ?
Créer nos classes et remarquer que l’ajout de migration ne fonctionne pas
Nous avons un projet asp.net mvc core qui appelle une librairie (un projet de type Class Library).
C’est dans ce projet que nous avons le Context entities.
Nous venons d’ajouter une propriété à une de nos classes.
Le réflexe à acquérir ? Créer une migration pour mettre à jour la base de données par la suite (avec un dotnet ef database update).
Pour se faire, vous allez suivre ces étapes :
- Compiler votre projet Class library
- Ouvrir une invite de commande sur le dossier où se trouve le projet
- Lancer la commande : dotnet ef migrations add MaNouvelleMigration
Dans le cas d’un projet asp.net core sans class library, ça doit fonctionner.
Or, ici, nous récupérons le message suivant :
The specified framework version ‘2.1’ could not be parsed
The specified framework ‘Microsoft.NETCore.App’, version ‘2.1’ was not found.
– Check application dependencies and target a framework version installed at:
C:\Program Files\dotnet\
– Installing .NET Core prerequisites might help resolve this problem:
http://go.microsoft.com/fwlink/?LinkID=798306&clcid=0x409
– The .NET Core framework and SDK can be installed from:
https://aka.ms/dotnet-download
– The following versions are installed:
2.0.7 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
2.1.3 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Ce qui est étrange, c’est que nous avons bien la version 2.1 d’installée (exactement la 2.1.3).
Ici, il manque en fait le moteur de fabrication d’entities
Ce moteur est en fait présent du côté asp.net mvc core :
string connectionString = this.Configuration.GetConnectionString(« DefaultContext »);
services.AddDbContext<DefaultContext>(options => options.UseSqlServer(connectionString), ServiceLifetime.Scoped);
Or, vu que nous sommes dans une classe library, il n’est pas reconnu comme projet asp.net.
Ainsi, vous devez installer et configurer plusieurs fichiers.
Installer la dll Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.Design.
Mais en relançant l’ajout de la migration, ça ne fonctionne toujours pas.
Obtention de l’erreur
Unable to create an object of type ‘DefaultContext’. Add an implementation of ‘IDesignTimeDbContextFactory<DefaultContext>’ to the project, or see https://go.microsoft.com/fwlink/?linkid=851728 for additional patterns supported at design time.
Il nous faut une Factory qui crée le Context Entities
Ici, en fait, lorsque nous sommes du côté asp.net core, il crée lui même notre context avec la méthode :
services.AddDbContext<DefaultContext>(options => options.UseSqlServer(connectionString), ServiceLifetime.Scoped);
Or, dans une classe Library, ce n’est pas fait automatiquement.
Ainsi, à vous de créer une classe, par exemple DefaultDesignTimeDbContextFactory qui implémente : ‘IDesignTimeDbContextFactory<DefaultContext>’.
Or, il nous pouvoir préciser que c’est une connexion sql server, et la connectionStrings à utiliser.
Installer Microsoft.Extensions.Configuration.FileExtensions
Ainsi, on va pouvoir définir le SetBasePath pour récupérer le fichier appsettings.json.
Ceci à ajouter à la configuration du ConfigurationBuilder.
Puis, vous devez préciser quel est le fichier de configuration
Vous allez d’abord installer la dll : Microsoft.Extensions.Configuration.Json.
Ce qui va vous permettre de préciser le fichier appsettings.json avec AddJsonFile(“appsettings.json”).
Après avoir préparer notre ConfigurationBuilder, nous allons ainsi pouvoir récupérer notre chaine de configuration :
string path = Directory.GetCurrentDirectory();
var builder = new ConfigurationBuilder()
.SetBasePath(path)
.AddJsonFile(« appsettings.json »);
var config = builder.Build();
var connectionString = config.GetConnectionString(« DefaultContext »);
Il nous reste à paramétrer le fait qu’il s’agit d’une connection sql server
Pour se faire, nous devons :
- Créer un builder des options du context : DbContextOptionsBuilder<DefaultContext> optionBuilder = new DbContextOptionsBuilder<DefaultContext>();
- Installer la dll pour sql server : Microsoft.EntityFrameworkCore.SqlServer
- Préciser ce paramétrage au DbContextOptionsBuilder : optionBuilder.UseSqlServer(connectionString);
- Passer les options au DbContext : return new DefaultContext(optionBuilder.Options);
Code final pour pouvoir créer une migration depuis un projet Class Library .net core
Ainsi, en ayant suivi toutes ces étapes, vous obtenez le code suivant pour la factory :
public class DefaultDesignTimeDbContextFactory : IDesignTimeDbContextFactory<DefaultContext>
{
public DefaultContext CreateDbContext(string[] args)
{
string path = Directory.GetCurrentDirectory();
var builder = new ConfigurationBuilder()
.SetBasePath(path)
.AddJsonFile(« appsettings.json »);
var config = builder.Build();
var connectionString = config.GetConnectionString(« DefaultContext »);
DbContextOptionsBuilder<DefaultContext> optionBuilder = new DbContextOptionsBuilder<DefaultContext>();
optionBuilder.UseSqlServer(connectionString);
return new DefaultContext(optionBuilder.Options);
}
}
Rebuilder le projet et relancer le dotnet ef migrations add
Après rebuild du projet et relancement de la commande dotnet ef migration add MaMigration, vous allez voir apparaitre un dossier Migrations avec la migration souhaitée !
And voilà