次の方法で共有


.NET .NET Aspire を使用してデータベース内のデータをシード処理する

この記事では、アプリの起動時にデータベースにデータをシードするように .NET.NET Aspire プロジェクトを構成する方法について説明します。 .NET Aspire を使用すると、SQL Server、PostgreSQL、MySQLなどの一般的なプラットフォームのデータベース スクリプトまたは Entity Framework Core を使用してデータをシードできます。

データをシード処理するタイミング

データをシード処理すると、データベース テーブルにデータ行が事前に設定されるため、アプリを使用してテストする準備が整います。 次のシナリオでデータをシードすることができます。

  • 製品カタログや顧客の一覧など、意味のある一連のデータに対して、アプリのさまざまな機能を手動で開発してテストします。
  • テスト スイートを実行して、特定のデータ セットで機能が特定の方法で動作することを確認します。

データを手動でシード処理するのは面倒で時間がかかるため、可能な場合はプロセスを自動化する必要があります。 起動時に .NET.NET Aspire プロジェクトのデータベース スクリプトを実行するには、ボリュームを使用します。 Entity Framework Coreなどのツールを使用してデータベースをシードすることもできます。このツールは、基になる多くの懸念事項を処理します。

コンテナー化されたデータベースについて

既定では、.NET.NET Aspire データベース統合はコンテナー化されたデータベースに依存するため、データをシード処理しようとすると次の課題が発生します。

  • .NET .NET Aspire は、アプリが再起動されるたびにコンテナーを破棄して再作成します。つまり、既定では、アプリが再起動されるたびにデータベースを再シードする必要があります。
  • 選択したデータベース テクノロジによっては、新しいコンテナー インスタンスで既定のデータベースが作成される場合と作成されない場合があります。つまり、データベース自体を作成する必要がある場合もあります。
  • 既定のデータベースが存在する場合でも、ほとんどの場合、特定のアプリに必要な名前やスキーマはありません。

.NET .NET Aspire では、ボリュームといくつかの構成を使用してこれらの課題を解決し、データを効果的にシードすることができます。

ボリュームと SQL スクリプトを使用してデータをシード処理する

ボリュームは、SQL スクリプトを使用するときにコンテナー化されたデータベースを自動的にシード処理する方法として推奨されます。 ボリュームは、一度に複数のコンテナーのデータを格納でき、高いパフォーマンスを提供し、バックアップや移行が簡単です。 .NET .NET Aspireでは、次の 3 つのパラメーターを受け取る ContainerResourceBuilderExtensions.WithBindMount メソッドを使用して、各リソース コンテナーのボリュームを構成します。

  • ソース: ボリューム マウントのソース パス。これは、ホスト上の物理的な場所です。
  • ターゲット: 保持するデータのコンテナー内のターゲット パス。

AppHost プロジェクトのサンプル ファイルから次のボリューム構成コードを検討してください。

var todosDbName = "Todos";
var todosDb = builder.AddPostgres("postgres")
    .WithEnvironment("POSTGRES_DB", todosDbName)
    .WithBindMount(
        "../DatabaseContainers.ApiService/data/postgres",
        "/docker-entrypoint-initdb.d")
    .AddDatabase(todosDbName);

この例では、.WithBindMount メソッド パラメーターによって次の構成が行われます。

  • ../DatabaseContainers.ApiService/data/postgres、データをシード処理するためにコンテナーで実行するローカル プロジェクトの SQL スクリプトへのパスを設定します。
  • /docker-entrypoint-initdb.d、コンテナーの起動時にスクリプトが実行されるように、コンテナー内のエントリ ポイントへのパスを設定します。

../DatabaseContainers.ApiService/data/postgres にある参照先の SQL スクリプトは、Todos テーブルを作成してシードします。

-- Postgres init script

-- Create the Todos table
CREATE TABLE IF NOT EXISTS Todos
(
    Id SERIAL PRIMARY KEY,
    Title text UNIQUE NOT NULL,
    IsComplete boolean NOT NULL DEFAULT false
);

-- Insert some sample data into the Todos table
INSERT INTO Todos (Title, IsComplete)
VALUES
    ('Give the dog a bath', false),
    ('Wash the dishes', false),
    ('Do the groceries', false)
ON CONFLICT DO NOTHING;

スクリプトは、新しいコンテナー インスタンスが作成されるたびに起動時に実行されます。

データベースシード処理の例

次の例では、さまざまなデータベース テクノロジの .WithBindMount メソッドを使用して適用された SQL スクリプトと構成を使用してデータをシードする方法を示します。

手記

データベース コンテナー サンプル アプリの にアクセスして、各データベース オプションの完全なプロジェクトとファイル構造を表示します。

の構成コード。AppHostProgram.cs ファイルは、必要なデータベース ファイルとフォルダーをマウントし、起動時に実行されるようにエントリポイントを構成します。

    .WithEnvironment("MYSQL_DATABASE", catalogDbName)
    // Mount the SQL scripts directory into the container so that the init scripts run.
    .WithBindMount("../DatabaseContainers.ApiService/data/mysql", "/docker-entrypoint-initdb.d")
    // Configure the container to store data in a volume so that it persists across instances.
    .WithDataVolume()
    // Keep the container running between app host sessions.
    .WithLifetime(ContainerLifetime.Persistent);

// Add the database to the application model so that it can be referenced by other resources.
var catalogDb = mysql.AddDatabase(catalogDbName);

// SQL Server container is configured with an auto-generated password by default

entrypoint.sh スクリプトは、マウントされた ./sqlserverconfig プロジェクト フォルダーに存在し、コンテナーの起動時に実行されます。 スクリプトは SQL Server を起動し、実行中であることを確認します。

#!/bin/bash

# Adapted from: https://github.com/microsoft/mssql-docker/blob/80e2a51d0eb1693f2de014fb26d4a414f5a5add5/linux/preview/examples/mssql-customize/entrypoint.sh

# Start the script to create the DB and user
/usr/config/configure-db.sh &

# Start SQL Server
/opt/mssql/bin/sqlservr

マウントされた ../DatabaseContainers.ApiService/data/sqlserver プロジェクト フォルダーに存在する init.sql SQL スクリプトによって、データベースとテーブルが作成されます。

-- SQL Server init script

-- Create the AddressBook database
IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = N'AddressBook')
BEGIN
  CREATE DATABASE AddressBook;
END;
GO

USE AddressBook;
GO

-- Create the Contacts table
IF OBJECT_ID(N'Contacts', N'U') IS NULL
BEGIN
    CREATE TABLE Contacts
    (
        Id        INT PRIMARY KEY IDENTITY(1,1) ,
        FirstName VARCHAR(255) NOT NULL,
        LastName  VARCHAR(255) NOT NULL,
        Email     VARCHAR(255) NULL,
        Phone     VARCHAR(255) NULL
    );
END;
GO

-- Ensure that either the Email or Phone column is populated
IF OBJECT_ID(N'chk_Contacts_Email_Phone', N'C') IS NULL
BEGIN
    ALTER TABLE Contacts
    ADD CONSTRAINT chk_Contacts_Email_Phone CHECK
    (
        Email IS NOT NULL OR Phone IS NOT NULL
    );
END;
GO

-- Insert some sample data into the Contacts table
IF (SELECT COUNT(*) FROM Contacts) = 0
BEGIN
    INSERT INTO Contacts (FirstName, LastName, Email, Phone)
    VALUES
        ('John', 'Doe', 'john.doe@example.com', '555-123-4567'),
        ('Jane', 'Doe', 'jane.doe@example.com', '555-234-5678');
END;
GO

Entity Framework Core を使用してデータをシード処理する

また、起動時に明示的に移行を実行することで、Entity Framework Core を使用して .NET Aspire プロジェクトのデータをシードすることもできます。 Entity Framework Core は、基になるデータベース接続とスキーマの作成を自動的に処理するため、コンテナーの起動時にボリュームを使用したり、SQL スクリプトを実行したりする必要がなくなります。

大事な

これらの種類の構成は開発中にのみ行う必要があるため、現在の環境コンテキストをチェックする条件付きを必ず追加してください。

API Service プロジェクトの Program.cs ファイルに次のコードを追加します。

// Register DbContext class
builder.AddSqlServerDbContext<TicketContext>("sqldata");

var app = builder.Build();

app.MapDefaultEndpoints();

if (app.Environment.IsDevelopment())
{
    // Retrieve an instance of the DbContext class and manually run migrations during startup
    using (var scope = app.Services.CreateScope())
    {
        var context = scope.ServiceProvider.GetRequiredService<TicketContext>();
        context.Database.Migrate();
    }
}

次の手順

データベース のシード処理は、さまざまなアプリ開発シナリオで役立ちます。 これらの手法と、次のチュートリアルで示されているリソース実装を組み合わせてみます。