【问题标题】:ASP.NET Core RC2 Seed DatabaseASP.NET Core RC2 种子数据库
【发布时间】:2023-03-21 06:40:01
【问题描述】:

我的问题是我正在尝试用数据植入 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 的优先级列表中非常高,但如果有一些关于如何完成这项琐碎任务或至少提供临时解决方法的文档,那就太好了。如果有人可以就如何做到这一点提供一些指导,将不胜感激。我觉得我已经接近解决方案,但无法将其拼凑起来。

感谢您的帮助。

【问题讨论】:

    标签: c# asp.net-core entity-framework-core asp.net-core-1.0


    【解决方案1】:

    假设您使用的是内置 DI 容器,这里有一种方法可以完成此操作。

    在启动类的 Configure 方法中引用种子方法,并将 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&lt;ApplicationDbContext&gt;()。我稍微修改了您的解决方案以将其用作扩展方法。
    • @MohammadAkbari 你似乎在挑毛病。注意 //... 执行其他种子操作行?这清楚地暗示他可能还有其他操作要执行。这里解决的问题是将上下文注入到种子方法中。
    • 当心服务定位器反模式,但同时也是很好的解决方法。我期待 EF Core 获得更多功能,以便在产品中使用。
    • 我最终使用了public static IApplicationBuilder Seed(this IApplicationBuilder app),这样我的创业公司就可以使用app.seed();
    • 我是个新手,非常仔细地遵循这个字符串,但不断收到关于范围界定的运行时错误。找到并进行了此更改(我使用的是核心 2.1 RC) .public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup() .UseDefaultServiceProvider(options => options.ValidateScopes =假)(blogs.msdn.microsoft.com/dotnet/2017/05/12/…
    【解决方案2】:

    您还可以使用 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));
    }
    

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

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

    最后,种子方法可以对重要表进行快速检查,因为可能重新创建数据库太重了:

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

    我希望它可以帮助您或其他人,至少作为另一种选择。

    【讨论】:

      【解决方案3】:

      如果您想从一个单独的类库运行您的 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
      

      【讨论】:

        猜你喜欢
        • 2016-09-18
        • 2018-02-23
        • 1970-01-01
        • 1970-01-01
        • 2016-10-23
        • 1970-01-01
        • 2013-11-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多