Programming & Development Note

C# とか JavaScript が好きなプログラマー1年生です。

【ASP.NET Core 2.0】データベースのシードの作成方法

以下の記事の続きです。

sanonosa-dev.hateblo.jp

データベースのシードとは

データベース初期化用のサンプルデータのことです。
アプリ起動時にデータベースにレコードが存在しない場合、自動でサンプルデータをインサートするプログラムを作成します。

公式のチュートリアルに沿って作成します。

docs.microsoft.com


[ Models ] を右クリックに SeedData クラス を追加します。
Program.csでアプリの起動時に呼びされます。
チュートリアルでは同期処理ですが、C#7.1以降では Main() メソッドを非同期に書けるので、非同期処理で作成します。

\models\seeddata.cs

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Threading.Tasks;

namespace RazorPagesMovie.Models
{
    public static class SeedData
    {
        public static async Task InitializeAsync(IServiceProvider serviceProvider)
        {
            using (var context = new MovieContext(
                serviceProvider.GetRequiredService<DbContextOptions<MovieContext>>()))
            {
                if (await context.Movie.AnyAsync())
                {
                    return;
                }

                await context.Movie.AddRangeAsync(
                    new Movie
                    {
                        Title = "When Harry Met Sally",
                        ReleaseDate = DateTime.Parse("1989-2-19"),
                        Genre = "Romantic Comedy",
                        Price = 7.99M
                    },

                    new Movie
                    {
                        Title = "Ghostbusters",
                        ReleaseDate = DateTime.Parse("1984-3-13"),
                        Genre = "Comedy",
                        Price = 8.99M
                    },

                    new Movie
                    {
                        Title = "Ghostbusters 2",
                        ReleaseDate = DateTime.Parse("1986-2-23"),
                        Genre = "Comedy",
                        Price = 9.99M
                    },

                    new Movie
                    {
                        Title = "Rio Bravo",
                        ReleaseDate = DateTime.Parse("1959-4-15"),
                        Genre = "Western",
                        Price = 3.99M
                    }
                );

                await context.SaveChangesAsync();
            }
        }
    }
}

シード作成のメソッドは非同期処理の慣例に従って InitializeAsync とします。
context.Movie.AnyAsync() でデータベースにレコードが存在するかをチェックしすでにデータが存在する場合は登録を行いません。
AddRangeAsync()Movie オブジェクトを追加します。
初期化はコレクション初期化子で行います。

Program.cs上記で作成した SeedData.InitializeAsync を呼び出すように編集します。

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using RazorPagesMovie.Models;
using Microsoft.EntityFrameworkCore;

namespace RazorPagesMovie
{
    public class Program
    {
        public static async Task Main(string[] args)
        {
            IWebHost host = BuildWebHost(args);

            using (IServiceScope scorp = host.Services.CreateScope())
            {
                IServiceProvider services = scorp.ServiceProvider;

                try
                {
                    MovieContext context = services.GetRequiredService<MovieContext>();
                    await context.Database.MigrateAsync();
                    await SeedData.InitializeAsync(services);
                }
                catch (Exception ex)
                {
                    ILogger<Program> logger = services.GetRequiredService<ILogger<Program>>();
                    logger.LogError(ex, "An error occurred seeding the DB.");
                }
            }

            await host.RunAsync();
        }

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .Build();
    }
}

C# 7.0以下の場合には上記Main() メソッド内を格納した MainAsync() メソッドを作成し、Main() メソッドから以下のように呼び出します。

public static void Main(string[] args)
{
    MainAsync(args).GetAwaiter().GetResult();
}

データベースのレコードすべて削除します。
アプリを起動し削除ページからすべてのデータを削除するか、SQL Server Object Explorer からデータベースを削除してパッケージマネージャーコンソールで Update-Database します。

アプリを起動すると以下のようにシードデータが表示されます。

f:id:sanonosa:20180217222311p:plain