créer automatiquement une base de données dans Entity Framework Core

100

Mon application qui est portée sur .NET Core utilisera le nouvel EF Core avec SQLite. Je souhaite créer automatiquement la base de données et les structures de table lors de la première exécution de l'application. Selon la documentation principale d'EF, cela se fait à l'aide de commandes manuelles

dotnet ef migrations add MyFirstMigration

dotnet ef database update

Cependant, je ne veux pas que l'utilisateur final entre ces commandes et je préférerais que l'application crée et configure la base de données pour la première utilisation. Pour EF 6, il existe des fonctionnalités telles que

Database.SetInitializer(new CreateDatabaseIfNotExists<MyContext>());

Mais dans EF Core, ils ne semblent pas exister. Je ne trouve aucun exemple ou documentation sur quelque chose d'équivalent pour EF core et il n'est pas mentionné dans la liste des fonctionnalités manquantes dans la documentation EF core. J'ai déjà configuré les classes de modèle pour que je puisse écrire du code pour initialiser la base de données en fonction des modèles, mais ce serait beaucoup plus facile si le framework le faisait automatiquement. Je ne veux pas créer automatiquement le modèle ou migrer, créez simplement les structures de table sur une nouvelle base de données.

Est-ce que je manque quelque chose ici ou la fonction de création automatique de table manque-t-elle dans le noyau EF?

Deandob
la source

Réponses:

146

Si vous avez créé les migrations, vous pouvez les exécuter dans Startup.cs comme suit.

 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
 {
      using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
      {
            var context = serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
            context.Database.Migrate();
      }

      ...

Cela créera la base de données et les tables en utilisant vos migrations ajoutées.

Si vous n'utilisez pas les migrations Entity Framework et que vous avez simplement besoin de votre modèle DbContext créé exactement tel qu'il est dans votre classe de contexte lors de la première exécution, vous pouvez utiliser:

 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
 {
      using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
      {
            var context = serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
            context.Database.EnsureCreated();
      }

      ...

Au lieu.

Si vous devez supprimer votre base de données avant de vous assurer qu'elle est créée, appelez:

            context.Database.EnsureDeleted();

Juste avant d'appeler EnsureCreated()

Adapté de: http://docs.identityserver.io/en/latest/quickstarts/7_entity_framework.html?highlight=entity

Ricardo Fontana
la source
1
Je suis encore assez nouveau dans EF, j'ai créé les classes qui définissent les structures de données en utilisant d'abord le code EF 6 "créer à partir de la base de données" à partir de Visual Studio en utilisant un fichier de base de données actuel. Je les ai ensuite coupés / collés dans la nouvelle solution VS dotnet core - donc je suppose que ce ne sont pas des migrations. Cela signifie-t-il que je dois créer un fichier de migration avant que le code ci-dessus puisse être utilisé?
deandob
2
Je suis désolé, j'ai fait une erreur dans ma réponse, si vous n'utilisez pas de migrations, vous pouvez utiliser la commande context.Database.EnsureCreated () / EnsureDeleted (), plus de détails dans blogs.msdn.microsoft.com/dotnet/2016 / 09/29 /…
Ricardo Fontana
2
Et si vous avez besoin des deux solutions? Nous venons de porter notre application sur UWP et avons commencé à utiliser EF Core, ce qui signifie que certains utilisateurs ont besoin que la base de données soit créée à partir de zéro, tandis que d'autres ont déjà la base de données. Existe-t-il un moyen de garantir que la première migration ne crée les tables initiales que si elles n'existent pas déjà? Votre réponse ne semble pas couvrir cela ou est-ce que je manque quelque chose?
Lars Udengaard
33

Ma réponse est très similaire à la réponse de Ricardo, mais je pense que mon approche est un peu plus simple simplement parce qu'il se passe tellement de choses dans sa usingfonction que je ne sais même pas comment cela fonctionne exactement à un niveau inférieur.

Donc, pour ceux qui veulent une solution simple et propre qui crée pour vous une base de données où vous savez exactement ce qui se passe sous le capot, c'est pour vous:

public Startup(IHostingEnvironment env)
{
    using (var client = new TargetsContext())
    {
        client.Database.EnsureCreated();
    }
}

Cela signifie à peu près que dans le DbContextque vous avez créé (dans ce cas, le mien est appelé TargetsContext), vous pouvez utiliser une instance de DbContextpour vous assurer que les tables définies dans la classe sont créées lorsque Startup.cs est exécuté dans votre application.

susieloo_
la source
10
Juste comme une information d' ici : EnsureCreatedcontourne totalement les migrations et crée simplement le schéma pour vous, vous ne pouvez pas mélanger cela avec des migrations. EnsureCreatedest conçu pour les tests ou le prototypage rapide où vous êtes d'accord pour supprimer et recréer la base de données à chaque fois. Si vous utilisez des migrations et que vous souhaitez les appliquer automatiquement au démarrage de l'application, vous pouvez utiliser à la context.Database.Migrate()place.
Thomas Schneiter
Cela répond à ma confusion pourquoi ma chaîne de connexion ne fonctionne pas ... :( Donc la base de données n'est pas automatiquement créée que vous devez spécifier Database.EnsureCreated () ce que j'ai fait dans mon constructeur DbContext. Merci beaucoup, cela me sauve du dilemme de 3 jours. X_X
pampi
Je voulais juste noter que je viens d'essayer de coller ceci dans mon fichier de démarrage et VS2019 m'a informé que IHostingEnvironmentc'est maintenant obsolète et que l'alternative recommandée est Microsoft.AspNetCore.Hosting.IWebHostEnvironment.
ctrl-z pls le
18

Si vous obtenez le contexte via la liste de paramètres de Configure dans Startup.cs, vous pouvez à la place faire ceci:

public void Configure(IApplicationBuilder app, IHostingEnvironment env,  LoggerFactory loggerFactory,
    ApplicationDbContext context)
 {
      context.Database.Migrate();
      ...
John Pankowicz
la source
1
À mon humble avis, c'est la meilleure solution: vous n'avez à vous soucier d'aucun service ni même du contexte de base de données, vous pouvez simplement utiliser le contexte que vous obtenez via l'injection de dépendances. Agréable!
Tobias
13

Pour EF Core 2.0+, j'ai dû adopter une approche différente car ils ont changé l'API. Depuis mars 2019, Microsoft vous recommande de placer le code de migration de votre base de données dans la classe d'entrée de votre application, mais en dehors du code de génération WebHost.

public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateWebHostBuilder(args).Build();
        using (var serviceScope = host.Services.CreateScope())
        {
            var context = serviceScope.ServiceProvider.GetRequiredService<PersonContext>();
            context.Database.Migrate();
        }
        host.Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}
Paul Stegler
la source
7

Si vous n'avez pas créé de migrations, il existe 2 options

1. créez la base de données et les tables à partir de l'application principale:

var context = services.GetRequiredService<YourRepository>();
context.Database.EnsureCreated();

2. créez les tables si la base de données existe déjà:

var context = services.GetRequiredService<YourRepository>();
context.Database.EnsureCreated();
RelationalDatabaseCreator databaseCreator =
(RelationalDatabaseCreator)context.Database.GetService<IDatabaseCreator>();
databaseCreator.CreateTables();

Merci à la réponse de Bubi

Nathan Alard
la source
2
quels sont vos services?
MichaelMao
Tous les documents que je lis montre de grands avertissements de la graisse autour des migrations en disant : « Ne pas utiliser EnsureCreatedou EnsureDeletedou Database.Migrateéchouera »
mwilson