私の問題は、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" }
);
}
...
}
データベースのシードはEntityFrameworkの優先順位リストの上位にあることを理解していますが、この簡単なタスクを実行する方法、または少なくとも一時的な回避策を提供する方法に関するドキュメントがあれば素晴らしいと思います。誰かがこれを行う方法についていくつかのガイダンスを提供することができれば、それは大いにありがたいです。私は解決策に近づいていると感じていますが、それをつなぎ合わせることができません。
助けてくれてありがとう。
組み込みのDIコンテナを使用していると仮定すると、これを実現する1つの方法があります。
スタートアップクラスのConfigureメソッドでシードメソッドを参照し、次のように、DbContextではなくIApplicationBuilderオブジェクトをパラメーターとして渡します。
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
}
}
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();
}
最後に、シードメソッドは重要なテーブルをすばやくチェックできます。おそらくdbの再作成が重すぎるためです。
public void Seed()
{
//....
if(context.Countries.Any())
return;
//...
}
少なくとも別の選択肢として、それがあなたや他の誰かに役立つことを願っています。
別のクラスライブラリからEFコードを実行し、シードを実行する場合は、次の操作を実行できます。これは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