web-dev-qa-db-fra.com

ASP.NET Core RC2 Seed Base de données

Mon problème est que j'essaie d'ensemencer des données dans une base de données Entity Framework Core et que, dans mon esprit, le code ci-dessous est efficace. J'ai réalisé que cela ne devrait pas être appelé dans le constructeur ApplicationDbContext et qu'il devrait être appelé à partir de startup mais je ne suis pas sûr de savoir comment procéder. 

EDIT: Basé sur la solution fournie par Ketrex, ma solution est la suivante:

Startup.cs:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        ... 

        app.ApplicationServices.GetRequiredService<ApplicationDbContext>().Seed();
    }

Extension de la graine:

public static class DbContextExtensions
{
    public static void Seed(this ApplicationDbContext context)
    {
        // Perform database delete and create
        context.Database.EnsureDeleted();
        context.Database.EnsureCreated();

        // Perform seed operations
        AddCountries(context);
        AddAreas(context);
        AddGrades(context);
        AddCrags(context);
        AddClimbs(context);

        // Save changes and release resources
        context.SaveChanges();
        context.Dispose();
    }

    private static void AddCountries(ApplicationDbContext context)
    {
        context.AddRange(
            new Country { Name = "England", Code = "En" },
            new Country { Name = "France", Code = "Fr" }
            );
    }

    ...
}

Je comprends que la création d’une base de données figure en bonne place sur la liste des priorités d’Entity Framework, mais il serait bon de disposer de documentation sur la manière de réaliser cette tâche triviale ou au moins de fournir une solution temporaire. Si quelqu'un peut donner des conseils sur la manière de procéder, ce serait grandement apprécié. Je pense que je suis sur le point de trouver une solution, mais que je ne peux pas la rassembler.

Merci pour toute aide.

11
Adam H

En supposant que vous utilisiez le conteneur DI intégré, voici une façon de procéder.

Référencez votre méthode de départ dans la méthode Configure de votre classe de démarrage et transmettez l'objet IApplicationBuilder en tant que paramètre à la place de DbContext, comme suit:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    //...
    // Put this at the end of your configure method
    DbContextSeedData.Seed(app);
}

Ensuite, modifiez votre méthode de départ pour accepter l'instance IApplicationBuilder. Vous pourrez ensuite créer une instance de DbContext et effectuer votre opération de départ, comme suit:

public static void Seed(IApplicationBuilder app)
{
    // Get an instance of the DbContext from the DI container
    using (var context = app.ApplicationServices.GetRequiredService<ApplicationDbContext>())
    {
        // perform database delete
        context.Database.EnsureDeleted;
        //... perform other seed operations
    }
}
11
Ketrex

Vous pouvez également utiliser la méthode Startup.cs ConfigureServices pour rendre votre ApplicationDbContext disponible (enregistrement de dbcontext en tant que service):

public void ConfigureServices(IServiceCollection services)
{
   var connectionString = Startup.Configuration["connectionStrings:DBConnectionString"];//this line is not that relevant, the most important thing is registering the DbContext
            services.AddDbContext<ApplicationDbContext>(o => o.UseSqlServer(connectionString));
}

puis ajoutez votre ApplicationDbContext comme dépendance dans votre méthode Configure qui appellera votre méthode d’extension de départ.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, ApplicationDbContext myApplicationDbContext)
{
    //...
    myApplicationDbContext.Seed();
}

Enfin, la méthode de départ pourrait effectuer une vérification rapide sur une table importante, car recréer la base de données est trop lourde:

public void Seed()
{
 //....      
 if(context.Countries.Any())
   return;
 //...
}

J'espère que cela vous aidera ou aidera quelqu'un d'autre, au moins comme autre option.

4
darmis

Si vous souhaitez exécuter votre code EF à partir d'une bibliothèque de classes distincte et effectuer un amorçage, procédez comme suit. Ceci utilise TSQL ...

1) Créez une nouvelle bibliothèque de classes . Ajoutez les dépendances suivantes avec NuGet ...

Microsoft.AspNetCore
Microsoft.AspNetCore.Identity.EntityFrameworkCore
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools

2) Pointez la console du gestionnaire de packages sur ce projet et exécutez ...

PM> add-migration Seeder01

puis...

PM> update-database

cela vous donne une migration vide.

3) Script des mises à jour comme quelque chose comme ...

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations;
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;
using System.IO;

namespace Test02.Data.Migrations
{
    public partial class Seeder01 : Migration
    {

        protected override void Up(MigrationBuilder migrationBuilder)
        {
            string sql = string.Empty;

            sql = "SET IDENTITY_INSERT State ON;";
            sql += "Insert into State (Id, Name) values ";
            sql += "(2, 'NSW'),";
            sql += "(3, 'VIC'),";
            sql += "(4, 'QLD'),";
            sql += "(5, 'SA')";
            sql += ";";
            sql += "SET IDENTITY_INSERT State OFF;";
            migrationBuilder.Sql(sql);

        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            string sql = string.Empty;
            sql = "delete State;";
            migrationBuilder.Sql(sql);


        }
    }
}

4) Revenir à la migration précédente avec ...

PM> add-migration {PriorMigrationName}

Rechargez la migration de départ et mettez à jour la base de données ...

PM> add-migration Seeder01
PM> update-database
0
CYoung