Comparteix a través de


Insertar datos en una base de datos utilizando .NET.NET Aspire

En este artículo, aprenderá a configurar proyectos .NET.NET Aspire para sembrar datos en una base de datos durante el inicio de la aplicación. .NET Aspire permite inicializar datos mediante scripts de base de datos o Entity Framework Core para plataformas comunes, como SQL Server, PostgreSQL y MySQL.

Cuándo se deben inicializar los datos

La inicialización de datos rellena previamente tablas de la base de datos con filas de datos, dejándolas listas para realizar pruebas a través de su aplicación. Es posible que desee inicializar los datos para los escenarios siguientes:

  • Desarrolle y pruebe manualmente diferentes características de la aplicación con un conjunto significativo de datos, como un catálogo de productos o una lista de clientes.
  • Ejecute conjuntos de pruebas para comprobar que las características se comportan de forma específica con un conjunto determinado de datos.

La introducción manual de datos es tediosa y consume mucho tiempo, por lo que debería automatizar el proceso siempre que sea posible. Utiliza volúmenes para ejecutar scripts de base de datos para proyectos .NET.NET Aspire durante el arranque. También puede inicializar su base de datos mediante herramientas, por ejemplo Entity Framework Core, que controla muchos aspectos subyacentes por usted.

Descripción de las bases de datos en contenedores

De forma predeterminada, las integraciones de bases de datos de .NET.NET Aspire se basan en bases de datos en contenedores, lo que crea los siguientes desafíos al intentar inicializar datos:

  • .NET .NET Aspire destruye y vuelve a crear contenedores cada vez que se reinicia la aplicación, lo que significa que, de forma predeterminada, tiene que volver a inicializar la base de datos cada vez que se reinicia la aplicación.
  • En función de la tecnología de base de datos seleccionada, la nueva instancia de contenedor puede o no crear una base de datos predeterminada, lo que significa que también puede tener que crear la propia base de datos.
  • Incluso si existe una base de datos predeterminada, lo más probable es que no tenga el nombre o el esquema deseados para la aplicación específica.

.NET .NET Aspire permite resolver estos desafíos mediante volúmenes y algunas configuraciones para inicializar datos de forma eficaz.

Inserción de datos mediante volúmenes y scripts SQL

Los volúmenes son la manera recomendada de inicializar automáticamente las bases de datos en contenedores al usar scripts SQL. Los volúmenes pueden almacenar datos para varios contenedores a la vez, ofrecer un alto rendimiento y son fáciles de realizar copias de seguridad o migrar. Con .NET.NET Aspire, configure un volumen para cada contenedor de recursos mediante el método ContainerResourceBuilderExtensions.WithBindMount, que acepta tres parámetros:

  • origen: la ruta de acceso de origen del montaje de volumen, que es la ubicación física en su host.
  • Objetivo: la ruta de acceso objetivo en el contenedor de los datos que quiere persistir.

Tenga en cuenta el siguiente código de configuración de volumen de un archivo Program.cs en un proyecto de ejemplo de AppHost:

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

En este ejemplo, los parámetros del método .WithBindMount configuran lo siguiente:

  • ../DatabaseContainers.ApiService/data/postgres establece una ruta de acceso al script SQL del proyecto local que desea ejecutar en el contenedor para inicializar los datos.
  • /docker-entrypoint-initdb.d establece la ruta de acceso a un punto de entrada del contenedor para que el script se ejecute durante el inicio del contenedor.

El script SQL al que se hace referencia en ../DatabaseContainers.ApiService/data/postgres crea y inicializa una tabla 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;

El script se ejecuta durante el inicio cada vez que se crea una nueva instancia de contenedor.

Ejemplos de propagación de bases de datos

En los ejemplos siguientes se muestra cómo inicializar datos mediante scripts y configuraciones de SQL aplicados mediante el método .WithBindMount para diferentes tecnologías de base de datos:

Nota

Visite la Aplicación de ejemplo contenedor de base de datos para ver el proyecto y la estructura completa de archivos para cada opción de base de datos.

Código de configuración del . AppHostProgram.cs archivo monta los archivos y carpetas de base de datos necesarios y configura un punto de entrada para que se ejecuten durante el inicio.

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

El script entrypoint.sh se encuentra en la carpeta montada del proyecto ./sqlserverconfig y se ejecuta cuando se inicia el contenedor. El script inicia SQL Server y comprueba que se está ejecutando.

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

El script SQL de init.sql que reside en la carpeta del proyecto ../DatabaseContainers.ApiService/data/sqlserver montada crea la base de datos y las tablas.

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

Siembra de datos mediante Entity Framework Core

También puede sembrar datos en proyectos de .NET Aspire usando Entity Framework Core al ejecutar específicamente las migraciones al inicio. Entity Framework Core controla las conexiones de base de datos subyacentes y la creación de esquemas, lo que elimina la necesidad de usar volúmenes o ejecutar scripts SQL durante el inicio del contenedor.

Importante

Estos tipos de configuraciones solo deben realizarse durante el desarrollo, por lo que debe asegurarse de agregar un condicional que compruebe el contexto del entorno actual.

Agregue el código siguiente al archivo Program.cs del proyecto de 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();
    }
}

Pasos siguientes

La propagación de bases de datos es útil en una variedad de escenarios de desarrollo de aplicaciones. Pruebe a combinar estas técnicas con las implementaciones de recursos que se muestran en los siguientes tutoriales: