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

Posted

技术标签:

【中文标题】在 Entity Framework 7 RC 1 和 ASP.NET MVC 6 中播种初始数据 [重复]【英文标题】:Seed initial data in Entity Framework 7 RC 1 and ASP.NET MVC 6 [duplicate] 【发布时间】:2016-04-04 19:28:35 【问题描述】:

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

微软提供的模板代码中没有DbMigrationsConfiguration类,也没有Seed方法。

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

【问题讨论】:

你也可以在MSDN博客中看到这篇文章:blogs.msdn.microsoft.com/dotnet/2016/09/29/… 【参考方案1】:

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

我们可以创建一个扩展IApplicationBuilder 的方法SeedData,然后通过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(); 行放在应用程序Startup 类的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

【讨论】:

【参考方案2】:

对于 EF Core RTM 1.0 和 ASP.NET Core 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();

【讨论】:

【参考方案3】:

我在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();
    

【讨论】:

【参考方案4】:

来自EF/MVC intro,只是:

    将你的DbContext(下面的SchoolContext)依赖注入到Startup.Configure()* 将您的DbContext 传递给执行以下操作的函数(下面的DbInitializer.Initialize):
      确保数据库为created or that it's migrated; context.Database.EnsureCreated(); 考虑context.Database.Migrate(); 如果已经播种则返回if (context.Students.Any()) return; 其他种子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 StudentFirstMidName="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 中完成 这里没有其他答案,只是依赖注入到配置中;他们要么GetService() 和/或GetRequiredService(),要么实例化一个新的 DbContext。您可能不需要那么多代码。再说一次,您可能需要这么多代码(即,如果已处理 Dependency-Injected DbContext,which is where the GetService() is necessary to create a new 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; 

Startup.cs内的Configure()方法中,调用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);
    

【讨论】:

以上是关于在 Entity Framework 7 RC 1 和 ASP.NET MVC 6 中播种初始数据 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework Core RC2 表名复数

MVC3 Entity Framework 4.1RC @Html.DropDownListFor 如何实际工作?

Entity Framework 5 和 XElement 字段

重置 Entity Framework 7 迁移

十分钟轻松让你认识Entity Framework 7

如何使用 Entity Framework 7 记录查询?