Entity Framework Core の In-Memory データベースに初期データを投入する
はじめに
テストや環境を汚さないために In-Memory データベースを使用する際に初期データを投入する方法を調べました。
データベースコンテキストのOnModelCreating
メソッドにフックすることで初期化します。
OnModelCreating
はデータベースコンテキストが初期化される際に1度だけ呼ばれます。
HasData
メソッドの初期化は、Entity Framework CoreによるID
の自動設定 が行われません。
そのため、自分でID
を取得する必要があります。
public DbSet<Book> Books { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder) =>
modelBuilder.Entity<Book>().HasData(
new Book { ID = 1, Name = "アンドロイドは電気羊の夢を見るか?" },
new Book { ID = 2, Name = "幼年期の終り" },
new Book { ID = 3, Name = "一九八四年" }
);
サンプルアプリ In-Memory データベース を使った Web API
プロジェクトの雛形の作成
# テンプレートには Web API を選択
$ dotnet new webapi -n SeedingInMemoryDb
$ cd SeedingInMemoryDb
# In-Memory データベースを使うためにライブラリをインストール
$ dotnet add Package Microsoft.EntityFrameworkCore.InMemory
モデルとデータベースコンテキスト
public class Book {
public int ID { get; set; }
public string Name { get; set; }
}
// using Microsoft.EntityFrameworkCore;
// using SeedingInMemoryDb.Models;
public class SampleInMemoryDbContext : DbContext {
public SampleInMemoryDbContext(DbContextOptions options) : base(options) { }
public DbSet<Book> Books { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder) =>
modelBuilder.Entity<Book>().HasData(
new Book { ID = 1, Name = "アンドロイドは電気羊の夢を見るか?" },
new Book { ID = 2, Name = "幼年期の終り" },
new Book { ID = 3, Name = "一九八四年" }
);
}
Startup
クラス
In-Memory データベースを使う設定をします。
いつも通りAddDbContext
する際にオプションからUseInMemoryDatabase
メソッドを呼びます。
UseInMemoryDatabase
メソッドの引数のデータベース名は必須みたいです。
// using Microsoft.EntityFrameworkCore;
// using Microsoft.Extensions.DependencyInjection;
public void ConfigureServices(IServiceCollection services) {
services.AddDbContext<SampleInMemoryDbContext>(options =>
options.UseInMemoryDatabase("sample_in_memory_db");
);
services.AddControllers();
}
エントリーポイント
In-Memory データベースを構築し初期データを投入します。
Program.cs
ではまだ DI コンテナが設定前であるため、データベースコンテキストを DI できません。
サービスプロバイダーからインスタンスを取得しEnsureCreatedAsync
メソッドを呼んで DB を作成します。
// using Microsoft.AspNetCore.Hosting;
// using Microsoft.Extensions.DependencyInjection;
// using Microsoft.Extensions.Hosting;
// using System.Threading.Tasks;
public class Program {
public static async Task Main(string[] args) {
IHost host = BuildHost(args);
using IServiceScope scope = host.Services.CreateScope();
IServiceProvider provider = scope.ServiceProvider;
using var context = provider.GetRequiredService<SampleInMemoryDbContext>();
await context.Database.EnsureCreatedAsync();
host.Run();
}
public static IHost BuildHost(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(web => web.UseStartup<Startup>()
.Build();
}
コントローラークラス
In-Memory データベース内の書籍を全件返すエンドポイント/api/books
を作ってみます。
// using Microsoft.AspNetCore.Mvc;
// using Microsoft.EntityFrameworkCore;
// using SeedingInMemoryDb.Models;
// using System.Collections.Generic;
// using System.Threading.Tasks;
[Route("api/[controller]")]
public class BooksController : Controller {
private readonly SampleInMemoryDbContext _db;
public BooksController(SampleInMemoryDbContext db) => _db = db;
[HttpGet]
public async Task<ActionResult<IEnumerable<Book>>> Get() =>
await _db.Books.ToListAsync();
}
実行結果
実行しlocalhost:{ポート番号}/api/books
にアクセスします。
In-Memory データベースに初期データが投入され、そのデータを全件取得できることが確認できました。
実行環境は以下の通りです。
- Windows X64
- Visual Studio 2019 (v16.4)
- .NET Core SDK 3.1.101
- C# 8.0
Author And Source
この問題について(Entity Framework Core の In-Memory データベースに初期データを投入する), 我々は、より多くの情報をここで見つけました https://qiita.com/Nossa/items/87010c056601dfbc1d84著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .