在 Entity Framework 7 RC 1 和 ASP.NET MVC 6 中播种初始数据

Seed initial data in Entity Framework 7 RC 1 and ASP.NET MVC 6

Entity Framework 7 似乎还没有原生支持种子数据 (https://github.com/aspnet/EntityFramework/issues/629)。

微软提供的模板代码中没有DbMigrationsConfigurationclass,没有Seed方法

那么如何在使用 Entity Framework 7 RC 1 的 ASP.NET MVC 6 Web 应用程序中播种数据?

我为自己找到了一个临时解决方法。

我们可以创建一个扩展 IApplicationBuilder 的方法 SeedData,然后通过 GetService 方法获取我们的数据库上下文 class 的一个实例,并将其用于播种数据.

这是我的扩展方法的样子:

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(); 行放入应用程序 Startup class 的 Configure 方法中(位于名为 Startup.cs 的文件中的 Web 项目中).

// 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
}

我在 Startup.cs 中创建了私有 Seed() 方法,但我也喜欢你的方法,因为它不仅可以在应用程序启动期间使用。

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

对于 EF Core RTM 1.0 和 ASP.NETCore RTM 1.0

首先创建种子方法。这里因为我们超出了当前请求的范围,所以我们必须手动创建它:

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

最后从Configure方法中调用SeedData()方法

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

您可以在 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);
    }

来自 EF/MVC intro,刚刚:

  1. 依赖项-将您的 DbContext(下面的 SchoolContext)直接注入 Startup.Configure()*
  2. 将您的 DbContext 传递给函数(下面的 DbInitializer.Initialize),该函数执行如下操作:
    1. 确保数据库是 created or that it's migratedcontext.Database.EnsureCreated(); 考虑 context.Database.Migrate();
    2. returns 如果已经播种 if (context.Students.Any()) { return; }
    3. 其他种子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() 的依赖注入是我的回答有价值的原因(即使另一个答案已经被接受。)

  1. 将您的 DbContext 依赖注入 Startup.Configure() 是在 EF/MVC Intro
  2. 中完成的
  3. 这里没有其他答案只是依赖注入配置;他们要么 GetService() and/or GetRequiredService(),要么 实例化一个新的 DbContext。您可能不需要那么多代码。再一次,你可能需要那么多代码,(即如果依赖注入的DbContext被处理,which is where the GetService() is necessary to create a new Scope.。如果我弄错了什么请downvote/edit/comment .