Udostępnij za pośrednictwem


Rozmieszczanie danych w bazie danych przy użyciu .NET.NET Aspire

Z tego artykułu dowiesz się, jak skonfigurować projekty .NET.NET Aspire w celu rozmieszczania danych w bazie danych podczas uruchamiania aplikacji. .NET Aspire umożliwia zasiewanie danych za pomocą skryptów bazy danych lub Entity Framework Core na typowych platformach, takich jak SQL Server, PostgreSQL i MySQL.

Kiedy należy zasiewać dane

Zasiewanie danych wstępnie wypełnia tabele bazy danych danymi, aby były gotowe do testowania w aplikacji. Możesz chcieć wprowadzić dane do następujących scenariuszy:

  • Ręczne opracowywanie i testowanie różnych funkcji aplikacji pod kątem znaczącego zestawu danych, takiego jak wykaz produktów lub lista klientów.
  • Uruchom zestawy testów, aby sprawdzić, czy funkcje zachowują się w określony sposób z danym zestawem danych.

Ręczne rozmieszczanie danych jest żmudne i czasochłonne, dlatego należy zautomatyzować proces, gdy jest to możliwe. Użyj woluminów, aby uruchamiać skrypty bazy danych dla projektów .NET.NET Aspire podczas uruchamiania. Bazę danych można również zainicjować za pomocą narzędzi takich jak Entity Framework Core, które zajmują się wieloma podstawowymi kwestiami.

Omówienie konteneryzowanych baz danych

Domyślnie integracje baz danych .NET.NET Aspire polegają na konteneryzowanych bazach danych, które tworzą następujące wyzwania podczas próby inicjowania danych.

  • .NET .NET Aspire niszczy i odtwarza kontenery przy każdym ponownym uruchomieniu aplikacji, co oznacza, że domyślnie trzeba ponownie rozmieszczać bazę danych za każdym razem, gdy aplikacja zostanie ponownie uruchomiona.
  • W zależności od wybranej technologii bazy danych nowe wystąpienie kontenera może lub nie może utworzyć domyślnej bazy danych, co oznacza również, że może być konieczne utworzenie samej bazy danych.
  • Nawet jeśli domyślna baza danych istnieje, najprawdopodobniej nie będzie miała żądanej nazwy ani schematu dla określonej aplikacji.

.NET .NET Aspire umożliwia rozwiązywanie tych problemów przy użyciu woluminów i kilku konfiguracji w celu efektywnego rozmieszczania danych.

Rozmieszczanie danych przy użyciu woluminów i skryptów SQL

Woluminy są zalecanym sposobem automatycznego rozmieszczania konteneryzowanych baz danych podczas korzystania ze skryptów SQL. Woluminy mogą jednocześnie przechowywać dane dla wielu kontenerów, oferować wysoką wydajność i łatwo tworzyć kopie zapasowe lub migrować. W przypadku .NET.NET Aspirenależy skonfigurować wolumin dla każdego kontenera zasobów przy użyciu metody ContainerResourceBuilderExtensions.WithBindMount, która akceptuje trzy parametry:

  • źródłowy: ścieżka źródłowa punktu montowania woluminu, która jest fizyczną lokalizacją na twoim hoście.
  • Target: Docelowa ścieżka w kontenerze danych, które mają być utrwalane.

Rozważ następujący kod konfiguracji woluminu z pliku Program.cs w przykładowym projekcie AppHost:

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

W tym przykładzie parametry metody .WithBindMount konfigurują następujące ustawienia:

  • ../DatabaseContainers.ApiService/data/postgres ustawia ścieżkę do skryptu SQL w projekcie lokalnym, do uruchomienia w kontenerze, aby załadować dane.
  • /docker-entrypoint-initdb.d ustawia ścieżkę do punktu wejścia w kontenerze, aby skrypt był uruchamiany podczas uruchamiania kontenera.

Przywołany skrypt SQL znajdujący się w ../DatabaseContainers.ApiService/data/postgres tworzy i wstawia dane do tabeli 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;

Skrypt jest uruchamiany podczas uruchamiania za każdym razem, gdy tworzone jest nowe wystąpienie kontenera.

Przykłady rozmieszczania bazy danych

W poniższych przykładach pokazano, jak inicjować dane przy użyciu skryptów SQL i konfiguracji zastosowanych przy użyciu metody .WithBindMount dla różnych technologii baz danych:

Notatka

Odwiedź przykładową aplikację kontenera bazy danych , aby wyświetlić pełną strukturę projektu i pliku dla każdej opcji bazy danych.

Kod konfiguracji w pliku .AppHostProgram.cs montuje wymagane pliki i foldery bazy danych oraz konfiguruje punkt wejścia, aby działały podczas uruchamiania.

    .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

Skrypt entrypoint.sh znajduje się w zainstalowanym folderze projektu ./sqlserverconfig i jest uruchamiany po uruchomieniu kontenera. Skrypt uruchamia SQL Server i sprawdza, czy działa.

#!/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

Skrypt init.sql SQL, który znajduje się w zainstalowanym folderze projektu ../DatabaseContainers.ApiService/data/sqlserver, tworzy bazę danych i tabele.

-- 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

Wypełnianie danych przy użyciu Entity Framework Core

Dane można również zasiewać w projektach .NET Aspire przy użyciu Entity Framework Core, jawnie uruchamiając migracje podczas uruchamiania aplikacji. Entity Framework Core obsługuje bazowe połączenia bazy danych i tworzenie schematu, co eliminuje konieczność używania woluminów lub uruchamiania skryptów SQL podczas uruchamiania kontenera.

Ważny

Te typy konfiguracji powinny być wykonywane tylko podczas programowania, dlatego należy dodać warunkowy, który sprawdza bieżący kontekst środowiska.

Dodaj następujący kod do pliku Program.cs projektu API Service.

// 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();
    }
}

Następne kroki

Rozmieszczanie bazy danych jest przydatne w różnych scenariuszach tworzenia aplikacji. Spróbuj połączyć te techniki z implementacjami zasobów przedstawionymi w następujących samouczkach: