데이터베이스에 데이터를 시드하기 위해 .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 ContainerResourceBuilderExtensions.WithBindMount 메서드를 사용하여 각 리소스 컨테이너에 대한 볼륨을 구성합니다. 이 메서드는 다음 세 가지 매개 변수를 허용합니다.
- 원본: 호스트의 물리적 위치에 있는 볼륨 마운트의 소스 경로입니다.
- 대상: 유지하려는 데이터의 컨테이너에 있는 대상 경로입니다.
샘플 AppHost 프로젝트의 Program.cs 파일에서 다음 볼륨 구성 코드를 고려합니다.
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 파일은 필요한 데이터베이스 파일 및 폴더를 탑재하고 시작 중에 실행되도록 진입점을 구성합니다.
// SQL Server container is configured with an auto-generated password by default
// but doesn't support any auto-creation of databases or running scripts on startup so we have to do it manually.
var sqlserver = builder.AddSqlServer("sqlserver")
// Mount the init scripts directory into the container.
.WithBindMount("./sqlserverconfig", "/usr/config")
// Mount the SQL scripts directory into the container so that the init scripts run.
.WithBindMount("../DatabaseContainers.ApiService/data/sqlserver", "/docker-entrypoint-initdb.d")
// Run the custom entrypoint script on startup.
.WithEntrypoint("/usr/config/entrypoint.sh")
// 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);
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();
}
}
다음 단계
데이터베이스 시드는 다양한 앱 개발 시나리오에서 유용합니다. 다음 자습서에 설명된 리소스 구현과 이러한 기술을 결합해 보세요.
.NET Aspire