Исходные данные семян в Entity Framework 7 RC 1 и ASP.NET MVC 6

Похоже, что в Entity Framework 7 еще нет встроенной поддержки семенных данных (https://github.com/aspnet/EntityFramework/issues/629).

В коде шаблона, предоставленном Microsoft, нет метода DbMigrationsConfiguration class, no Seed.

Итак, как загружать данные в веб-приложение ASP.NET MVC 6, использующее Entity Framework 7 RC 1?

Ответы

Ответ 1

Я нашел временное обходное решение для себя.

Мы можем создать метод SeedData, который расширяет IApplicationBuilder, а затем получает экземпляр нашего класса контекста базы данных с помощью метода GetService и использует его для посева данных.

Вот как выглядит мой метод расширения:

using Microsoft.AspNet.Builder;
using Microsoft.Extensions.DependencyInjection;

public static class DataSeeder
{
    // TODO: Move this code when seed data is implemented in EF 7

    /// <summary>
    /// This is a workaround for missing seed data functionality in EF 7.0-rc1
    /// More info: https://github.com/aspnet/EntityFramework/issues/629
    /// </summary>
    /// <param name="app">
    /// An instance that provides the mechanisms to get instance of the database context.
    /// </param>
    public static void SeedData(this IApplicationBuilder app)
    {
        var db = app.ApplicationServices.GetService<ApplicationDbContext>();

        // TODO: Add seed logic here

        db.SaveChanges();
    }
}

Чтобы использовать его, поместите строку app.SeedData(); в метод Configure класса Startup приложения (находящегося в веб-проекте в файле с именем Startup.cs).

// This method gets called by the runtime.
// Use this method to configure the HTTP request pipeline.
public void Configure(
    IApplicationBuilder app,
    IHostingEnvironment env,
    ILoggerFactory loggerFactory)
{
    app.SeedData();

    // Other configuration code
}

Ответ 2

Для EF Core RTM 1.0 и ASP.NET Core RTM 1.0

Сначала создайте метод семени. Здесь, поскольку мы вышли из области текущего запроса, мы должны создать его manulally:

using System.Collections.Generic;
using System.Linq;
using Core1RtmEmptyTest.Entities;
using Microsoft.Extensions.DependencyInjection;

namespace Core1RtmEmptyTest.Migrations
{
    public static class ApplicationDbContextSeedData
    {
        public static void SeedData(this IServiceScopeFactory scopeFactory)
        {
            using (var serviceScope = scopeFactory.CreateScope())
            {
                var context = serviceScope.ServiceProvider.GetService<ApplicationDbContext>();
                if (!context.Persons.Any())
                {
                    var persons = new List<Person>
                    {
                        new Person
                        {
                            FirstName = "Admin",
                            LastName = "User"
                        }
                    };
                    context.AddRange(persons);
                    context.SaveChanges();
                }
            }

        }
    }
}

Затем укажите правильное время жизни ApplicationDbContext

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(ServiceLifetime.Scoped);

И, наконец, вызовите метод SeedData() из метода Configure

public void Configure(IServiceScopeFactory scopeFactory)
{
    scopeFactory.SeedData();

Ответ 3

Я создал частный Seed() метод в моем Startup.cs, но мне также нравится ваш подход, потому что он может использоваться не только во время запуска приложения.

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

private void Seed()
{
    using (var db = new MyDbContext())
    {
        db.Database.Migrate();

        // Seed code

        db.SaveChanges();
    }
}

Ответ 4

Из ввод EF/MVC, просто:

  • зависимость - введите DbContext (SchoolContext ниже) непосредственно в Startup.Configure() *
  • передайте DbContext функции (DbInitializer.Initialize ниже), которая делает что-то вроде:
    • обеспечить, чтобы база данных создала или, которую она перенесла; context.Database.EnsureCreated(); рассмотрим context.Database.Migrate();
    • возвращает, если уже посеял if (context.Students.Any()) { return; }
    • else seed context.Students.Add({...}); context.SaveChanges();

Как здесь:

public void Configure(..., ..., SchoolContext context)
{

    ...
    DbInitializer.Initialize(context);
}

...

public static class DbInitializer
{
    public static void Initialize(SchoolContext context)
    {
        context.Database.EnsureCreated();

        // Look for any students.
        if (context.Students.Any())
        {
            return;   // DB has been seeded
        }

        var students = new Student[]
        {
            new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2005-09-01")}, ...
        };
        foreach (Student s in students)
        {
            context.Students.Add(s);
        }
        context.SaveChanges();
        ...

* Зависимость - инъекция в Startup.Configure() - вот почему мой ответ достоин (хотя другой ответ уже принят.)

  • Зависимость-впрыскивание DbContext в Startup.Configure() выполняется в EF/MVC Intro
  • Никакой другой ответ здесь просто зависит - вводит в Configure; они либо GetService(), и/или GetRequiredService(), либо создают новый DbContext. Вам может не понадобиться такой код. Опять же, вам может нужен такой код (т.е. Если был установлен DbContext с зависимостями, где находится GetService() необходимо создать новый Scope. Пожалуйста, уменьшите или отредактируйте/комментарий, если я что-то ошибся.

Ответ 5

Вы можете создать статический метод семени внутри ApplicationDbContext и передать IApplicationBuilder в качестве параметра. Затем вызовите этот метод в Startup.cs.

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }


    public static void Seed(IApplicationBuilder applicationBuilder)
    {
        using (var context=applicationBuilder.ApplicationServices.GetRequiredService<ApplicationDbContext>())
        {
            context.Database.EnsureDeleted();
            context.Database.EnsureCreated();
            for(int i = 1; i< 1000; i++)
            {
                context.Movies.Add(new Movie
                {
                   Genre = "Action",
                   ReleaseDate =DateTime.Today,
                   Title = "Movie "+i
                });
            }
            context.SaveChanges();
        }
    }

    public DbSet<Movie> Movies { get; set; }
}

В Configure() внутри Startup.cs вызовите ApplicationDbContext.Seed(app)

      public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
            app.UseBrowserLink();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();

        app.UseIdentity();


        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
        ApplicationDbContext.Seed(app);
    }