ASP.NET Core RC2 Seed Database

Моя проблема в том, что я пытаюсь заполнить базу данных Entity Framework Core данными, и, на мой взгляд, приведенный ниже код демонстрирует работу. Я понял, что это не должно называться вApplicationDbContext конструктор и должен быть вызван изstartup но я не уверен, как это сделать.

РЕДАКТИРОВАТЬ: На основе решения, предоставленного Ketrex, мое решение заключается в следующем:

Startup.cs:

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

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

Расширение семян:

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" }
            );
    }

    ...
}

Я понимаю, что заполнение базы данных занимает достаточно высокое место в списке приоритетов для Entity Framework, но было бы замечательно, если бы была некоторая документация о том, как решить эту тривиальную задачу, или, по крайней мере, обеспечить временное решение проблемы. Если кто-то может дать некоторые рекомендации о том, как это сделать, это будет с благодарностью. Я чувствую, что близок к решению, но просто не могу собрать его воедино.

Спасибо за любую помощь.

Ответы на вопрос(3)

Решение Вопроса

Предполагая, что вы используете встроенный контейнер DI, вот один из способов сделать это.

Ссылайтесь на ваш метод seed в методе Configure вашего класса запуска и передайте объект IApplicationBuilder в качестве параметра вместо DbContext, например так:

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

Затем измените ваш метод seed, чтобы он принимал экземпляр IApplicationBuilder. Затем вы сможете раскрутить экземпляр DbContext и выполнить начальную операцию, например:

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
    }
}
 Brian16 окт. 2017 г., 06:12
Я в конечном итоге с помощьюpublic static IApplicationBuilder Seed(this IApplicationBuilder app) чтобы мой стартап мог просто использоватьapp.seed();
 James08 февр. 2017 г., 00:39
Остерегайтесь анти-паттерна сервисного локатора, но в то же время приятного обходного пути. Я с нетерпением жду, когда EF Core получит больше функций, чтобы его можно было использовать в Prod.
 Adam H26 июн. 2016 г., 19:59
Спасибо вам большое! Именно эта линияapp.ApplicationServices.GetRequiredService<ApplicationDbContext>() что я скучал. Я немного изменил ваше решение, чтобы использовать его в качестве метода расширения.
 Mohammad Akbari12 июл. 2016 г., 09:47
проблема: context.Database.EnsureDeleted () удалить __EFMigrationsHistory также !!!
 Ketrex12 июл. 2016 г., 18:57
@MohammadAkbari ты, кажется, выбираешь гниды. Обратите внимание на // ... выполнить другую строку операций с семенами? Это явно подразумевает, что он может выполнять другие операции. Проблема, решаемая здесь, заключалась в том, чтобы внедрить контекст в метод семени.
 user148976530 мая 2018 г., 01:17
Я очень новичок и очень внимательно следил за этой строкой, но продолжал получать ошибку во время выполнения при определении области видимости. Нашел и сделал это изменение (я использую ядро ​​2.1 RC). Public static IWebHost BuildWebHost (string [] args) => WebHost.CreateDefaultBuilder (args) .UseStartup <Startup> () .UseDefaultServiceProvider (options => options.ValidateScopes = ложный) (blogs.msdn.microsoft.com/dotnet/2017/05/12/...)

Вы также можете использовать из Startup.csConfigureServices способ сделать ваш ApplicationDbContext доступным (регистрация dbcontext как сервиса):

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));
}

а затем добавьте свой ApplicationDbContext в качестве зависимости в вашемConfigure метод, который вызовет ваш метод расширения семени.

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

Наконец, метод seed мог бы быстро проверить важную таблицу, потому что, возможно, воссоздание БД слишком тяжело:

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

Я надеюсь, что это поможет вам или кому-то еще, по крайней мере, в качестве другого варианта.

Если вы хотите запустить код EF из отдельной библиотеки классов и выполнить Seeding, вы можете сделать следующее. Это использует TSQL ...

1) Создать новую библиотеку классов. Добавьте следующие зависимости с NuGet ...

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

2) Направьте консоль диспетчера пакетов на этот проект и запустите ...

PM> add-migration Seeder01

затем...

PM> update-database

это дает вам пустую миграцию.

3) Сценарий обновления как что-то вроде ...

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) Вернитесь к предыдущей миграции с ...

PM> add-migration {PriorMigrationName}

Перезагрузите начальную миграцию и обновите базу данных ...

PM> add-migration Seeder01
PM> update-database

Ваш ответ на вопрос