ASP.NET Core RC2 种子数据库

11

我的问题是我正在尝试使用数据填充实体框架核心数据库,我认为下面的代码应该可以工作。我意识到这不应该在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个回答

11

假设您正在使用内置的 DI 容器,以下是一种可以实现此目标的方法。

在 startup 类的 Configure 方法中引用您的 seed 方法,并将 IApplicationBuilder 对象作为参数传递,而不是 DbContext,就像这样:

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

接下来,修改您的种子方法以接受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
    }
}

非常感谢!我所缺失的是这行代码app.ApplicationServices.GetRequiredService<ApplicationDbContext>()。我稍作修改,将其用作扩展方法。 - Adam H
1
@MohammadAkbari,你似乎在挑毛病。注意到这一行吗? //... perform other seed operations 它清楚地暗示了他可能有其他操作要执行。这里解决的问题是将上下文注入种子方法中。 - cygnim
注意服务定位器反模式,但同时也有不错的解决方法。我期待 EF Core 获得更多功能,以便可以在生产中使用。 - Lotok
最終我使用了public static IApplicationBuilder Seed(this IApplicationBuilder app),這樣我的啟動就可以只使用app.seed(); - Brian Webb
我是一个非常新手,非常仔细地遵循了这个字符串,但一直出现关于作用域的运行时错误。找到并进行了更改(我正在使用core 2.1 RC)。.public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .UseDefaultServiceProvider(options => options.ValidateScopes = false) (https://blogs.msdn.microsoft.com/dotnet/2017/05/12/announcing-ef-core-2-0-preview-1/) - user1489765

4
您可以在Startup.cs的ConfigureServices方法中将您的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));
}

然后,在您的Configure方法中添加您的ApplicationDbContext作为依赖项,该方法将调用您的种子扩展方法。

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

最后,seed方法可以快速检查重要表格,因为重新创建数据库可能太过繁重:

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

我希望这可以帮助你或其他人,至少作为另一个选项。

0
如果您想从单独的类库中运行EF代码并在其中进行种子数据填充,可以按照以下步骤操作。这是使用TSQL的方法...
1)创建一个新的类库。 2)使用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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接