Almacenamiento de datos en bases de datos compatibles con SQL

Completado

La pila de .NET Aspire está diseñada para que sea más productiva y le ayude a crear aplicaciones web sólidas, escalables y seguras. Puede almacenar datos relacionales estructurados rápidamente agregando uno de los componentes de Aspire admitidos.

Los componentes de base de datos compatibles con SQL actuales son:

  • Bases de datos de PostgreSQL
  • Bases de datos SQL Database
  • Bases de datos de Oracle
  • Bases de datos de MySQL

Nota:

Microsoft puede agregar compatibilidad con otros sistemas de base de datos y terceros también pueden contribuir, por lo que esta lista puede expandirse.

En esta unidad, aprenderá sobre tres de estos componentes, qué bases de datos son compatibles con Entity Framework Core y cómo usarlos para almacenar y recuperar datos.

Cómo agregar un componente de base de datos al proyecto

Sea cual sea la base de datos que elija, el método para agregar un componente de base de datos .NET Aspire a su proyecto es el mismo.

En el proyecto host de la aplicación:

  • Instale el componente de hospedaje de .NET Aspire en el proyecto de host de la aplicación.
  • Registre una base de datos y cree un contenedor para él en el host de la aplicación de la solución.
  • Pase una referencia a los proyectos que necesitan acceso al contenedor creado que hospeda la base de datos.

En los proyectos que usan la base de datos:

  • Agregue el componente de .NET Aspire con un paquete NuGet a los proyectos que requieren acceso a datos. Opcionalmente, si hay un componente de Entity Framework (EF) de .NET Core, puede usarlo en su lugar.
  • Registre el origen de datos o el contexto de la base de datos para EF, en el archivo Program.cs del proyecto.
  • Use la inserción de dependencias para insertar el origen de datos en los servicios.

Veamos cómo realizar estos pasos para cada una de las bases de datos compatibles.

Uso de los componentes PostgreSQL de .NET Aspire

Los componentes de PostgreSQL de .NET Aspire requieren cambios en el proyecto host de la aplicación y en los microservicios que usan las bases de datos.

Configuración del host de la aplicación

Comience instalando el componente de hospedaje adecuado en el host de la aplicación:

dotnet add package Aspire.Hosting.PostgreSQL --prerelease

A continuación, para registrar una base de datos y crear un contenedor para ella, agregue este código al archivo Program.cs del host de la aplicación:

var postgres = builder.AddPostgres("postgres");
var postgresdb = postgres.AddDatabase("postgresdb");

También debe pasar una referencia al servicio de base de datos a los proyectos que lo consuman:

var northernTradersCatalogAPI = builder.AddProject<Projects.NorthernTraders_CatalogAPI>()
                                       .WithReference(postgresdb);

Configuración de los proyectos de consumo

Para instalar el componente de PostgreSQL de .NET Aspire, use un comando como este en los proyectos de .NET Aspire:

dotnet add package Aspire.Npgsql --prerelease

O bien, para usar el componente de PostgreSQL de Entity Framework Core de .NET Aspire, use este comando en su lugar:

dotnet add package Aspire.Npgsql.EntityFrameworkCore.PostgreSQL --prerelease

Como alternativa, puede usar el acceso directo Agregar > componente aspire de .NET en Visual Studio para instalar el componente desde el administrador de paquetes NuGet:

Captura de pantalla que muestra el administrador de paquetes NuGet en Visual Studio con componentes de PostgreSQL de .NET Aspire.

El código del archivo Program.cs del proyecto *. AppHost crea la base de datos y la pasa a los proyectos que quieren usarlo:

var postgres = builder.AddPostgres("pg")
                      .AddDatabase("postgresdb");

var exampleProject = builder.AddProject<Projects.SampleProject>()
                            .WithReference(postgres);

Algunos de los componentes de base de datos de .NET Aspire también permiten crear un contenedor para las herramientas de administración de bases de datos. Para agregar PgAdmin a la solución para administrar la base de datos de PostgreSQL, use este código:

var postgresdb = builder.AddPostgres("pg")
                        .AddDatabase("postgresdb")
                        .WithPgAdmin();

La ventaja de permitir que .NET Aspire cree el contenedor es que no es necesario realizar ninguna configuración para conectar PgAdmin a la base de datos de PostgreSQL, es todo automático.

Uso de una base de datos de PostgreSQL

En cualquier proyecto en el que quiera usar la base de datos, agregue un origen de datos para representar la conexión a PostgreSQL. En el archivo Program.cs, este código registra la base de datos:

builder.AddNpgsqlDataSource("postgresdb");

O para usar el componente Entity Framework Core, registre el contexto de la base de datos:

builder.AddNpgsqlDbContext<YourDbContext>("postgresdb");

Una vez registrada la base de datos en el proyecto de consumo, puede interactuar con el origen de datos en cualquier momento que lo necesite mediante la inserción de dependencias:

public class YourService(NpgsqlDataSource dataSource)
{
    public async Task<IEnumerable<Catalog>> GetCatalog()
	{
        const string query = "SELECT * FROM catalog";
        using var dbConnection = dataSource.OpenConnection();
        var results = await dbConnection.QueryAsync<Catalog>(command);
        return queryResult.ToArray();
	}
}

O bien, puede recuperar el contexto de la base de datos YourDbContext para interactuar con la base de datos:

public class YourService(YourDbContext context)
{
    public async Task<IEnumerable<Catalog>> GetCatalog()
	{
        var items = await context.ObjectItems;
        if (item is null)
        {
            return Results.NotFound();
        }
		else
		{
		    return items;
		}
	}
}

Configuración del componente de PostgreSQL

La pila de .NET Aspire intenta reducir la cantidad de configuración que debe realizar. Con la inserción de dependencias y la detección de servicios, puede acceder a la base de datos sin necesidad de configurar las cadenas de conexión en los proyectos.

El uso del proyecto host de la aplicación para crear el contenedor de base de datos y pasarlo como referencia a los proyectos, permite que los proyectos receptores accedan a la ubicación de la base de datos, las cadenas de conexión y los puertos. No es necesario administrar variables de entorno ni archivos appsettings.json.

Pero, si lo desea, o necesita más control sobre cómo se configura la base de datos, hay más opciones.

Utilizando una cadena de conexión

En el proyecto que requiere la base de datos, se usa una cadena de conexión para conectarse a la base de datos. Este enfoque es útil cuando necesita conectarse a una base de datos que no está registrada en el host de la aplicación.

builder.AddNpgsqlDataSource("NpgsqlConnectionString");

A continuación, en el archivo de configuración, puede agregar la cadena de conexión:

{
  "ConnectionStrings": {
    "NpgsqlConnectionString": "Host=myserver;Database=postgresdb;User id=myuser;Password=mypassword"
  }
}

Uso de proveedores de configuración

.NET Aspire tiene una característica de componentes que les permite admitir un Microsoft.Extensions.Configuration. El componente de PostgreSQL admite esta característica y, de forma predeterminada, busca la configuración mediante la clave Aspire:Npgsql. En los proyectos que usan appsettings.json, una configuración de ejemplo podría tener este aspecto:

{
  "Aspire": {
    "Npgsql": {
      "ConnectionString": "Host=myserver;Database=postgresdb;User id=myuser;Password=mypassword",
      "HealthChecks": true,
      "Tracing": true,
      "Metrics": true
    }
  }
}

La configuración anterior establece la cadena de conexión, habilitando las comprobaciones de estado, el seguimiento y las métricas del componente de PostgreSQL. A continuación, el código ya no necesita especificar la cadena de conexión, simplemente use builder.AddNpgsqlDataSource();.

Si usa el componente de PostgreSQL de Entity Framework Core, puede usar la clave Aspire:Npgsql:EntityFrameworkCore:PostgreSQL para configurar el contexto de la base de datos:

{
  "Aspire": {
    "Npgsql": {
      "EntityFrameworkCore": {
        "PostgreSQL": {
          "ConnectionString": "Host=myserver;Database=postgresdb;User id=myuser;Password=mypassword",
          "MaxRetryCount": 0,
          "HealthChecks": false,
          "Tracing": false
        }
      }
    }
  }
}

Para obtener más información sobre las opciones de configuración de Entity Framework, consulte la documentación de .NET Aspire.

Uso de delegados insertados

La última opción es pasar un delegado insertado configureSettings al método AddNpgsqlDataSource. Este delegado permite configurar las opciones del componente de base de datos directamente con código:

builder.AddNpgsqlDataSource(
    "postgresdb", static settings => settings.HealthChecks = false);

Uso de los componentes de la base de datos SQL de .NET Aspire

El patrón anterior es el mismo para el componente de la base de datos SQL. Los cambios realizados en el proyecto host de la aplicación y los microservicios que consumen el servicio de base de datos.

Configuración del host de la aplicación

Para instalar el componente de hospedaje de la base de datos SQL, use este comando:

dotnet add package Aspire.Hosting.SqlServer --prerelease

Para registrar el contenedor y la base de datos, agregue este código al archivo Program.cs del host de la aplicación:

var sql = builder.AddSqlServer("sql");
var sqldb = sql.AddDatabase("sqldb");

A continuación, pase una referencia al servicio de base de datos a los proyectos que lo consuman:

var northernTradersCatalogAPI = builder.AddProject<Projects.NorthernTraders_CatalogAPI>()
                                       .WithReference(sqldb);

Configuración de los proyectos de consumo

Para instalar el componente de la base de datos SQL de .NET Aspire, use un comando como este en los proyectos de .NET Aspire:

dotnet add package Aspire.Microsoft.Data.SqlClient --prerelease

O bien, para usar el componente de SqlServer de Entity Framework Core de .NET Aspire, use este comando en su lugar:

dotnet add package Aspire.Microsoft.EntityFrameworkCore.SqlServer --prerelease

Estos paquetes NuGet también se pueden agregar mediante el acceso directo Agregar > Componente de .NET Aspire en Visual Studio.

El código del archivo Program.cs del proyecto *. AppHost para acceder a la base de datos es similar al ejemplo de PostgreSQL:

var sqlServer = builder.AddSqlServer("sql")
                       .AddDatabase("sqldata");

var myService = builder.AddProject<Projects.MyService>()
                       .WithReference(sqlServer);

Uso de una base de datos de SQL Server

En los proyectos que necesitan acceso a SQL, en el archivo Program.cs, este código registra el contexto de la base de datos de Entity Framework:

builder.AddSqlServerDbContext<YourDbContext>("sqldata");

Una vez registrada la base de datos en el proyecto de consumo, puede interactuar con el contexto de la base de datos YourDbContext mediante la inserción de dependencias. Este código de ejemplo recupera las previsiones meteorológicas de una base de datos y selecciona una al azar para devolver:

app.MapGet("/weatherforecast", async (YourDbContext context) =>
{
  var rng = new Random();
  var forecasts = await context.Forecasts.ToListAsync();
  var forecast = forecasts[rng.Next(forecasts.Count)];
  return forecast;
});

Configuración del componente de SQL Server

Como antes, si usa el mismo nombre de base de datos en el host de la aplicación y el proyecto de consumo, no es necesario configurar la conexión entre la base de datos de SQL Server y los proyectos. El componente de SQL Server de .NET Aspire también admite otras formas de configurar el componente.

Uso de proveedores de configuración

El componente de SQL Server también admite Microsoft.Extensions.Configuration. De forma predeterminada, busca la configuración mediante la clave Aspire:SqlServer:SqlClient. En los proyectos que usan appsettings.json, una configuración de ejemplo podría tener este aspecto:

{
  "Aspire": {
    "SqlServer": {
      "SqlClient": {
        "ConnectionString": "YOUR_CONNECTIONSTRING",
        "HealthChecks": true,
        "Tracing": false,
        "Metrics": false
      }
    }
  }
}

Uso de configuraciones insertadas

Al agregar el componente de SQL Server, puede pasar un delegado insertado configureSettings al método AddSqlServerClient. Este delegado permite configurar las opciones del componente de base de datos directamente con código:

builder.AddSqlServerClient("sqldata", static settings => settings.HealthChecks = false);

Puede pasar cualquiera de las opciones admitidas:

  • ConnectionString: Cadena de conexión de la base de datos de SQL Server
  • HealthChecks: Valor booleano que indica si la comprobación de estado de la base de datos está habilitada
  • Tracing: Valor booleano que indica si el seguimiento de OpenTelemetry está habilitado
  • Metrics: Valor booleano que indica si las métricas de OpenTelemetry están habilitadas

Conexión a varias bases de datos

El componente de SQL Server admite varias conexiones a través de instancias con nombre. Por ejemplo, puede conectarse a dos bases de datos de SQL Server diferentes en el mismo proyecto:

{
  "Aspire": {
    "SqlServer": {
      "SqlClient": {
        "INSTANCE_1": {
          "ServiceUri": "YOUR_URI",
          "HealthChecks": false
        },
        "INSTANCE_2": {
          "ServiceUri": "YOUR_URI",
          "HealthChecks": false
        }
      }
    }
  }
}

Con esta configuración, puede conectarse a las dos bases de datos diferentes del mismo proyecto:

builder.AddSqlServerClient("INSTANCE_1");
builder.AddSqlServerClient("INSTANCE_2");

Uso del componente de MySQL

Para instalar el componente de MySQL de .NET Aspire, use un comando como este en los proyectos de .NET Aspire que requieran acceso a datos:

dotnet add package Aspire.MySqlConnector --prerelease

O use el acceso directo Agregar > componente aspire de .NET en Visual Studio para instalar el componente desde el administrador de paquetes NuGet.

El código del archivo Program.cs del proyecto *. AppHost para acceder a la base de datos es similar al ejemplo de PostgreSQL:

var mysqldb = builder.AddMySql("mysql")
                     .AddDatabase("mysqldb")
                     .WithPhpMyAdmin();

var myService = builder.AddProject<Projects.MyService>()
                       .WithReference(mysqldb);

Al igual que el componente de PostgreSQL, el componente de MySQL también permite crear un contenedor para las herramientas de administración de bases de datos. En el ejemplo anterior se agrega PhpMyAdmin a la solución.

Uso de una base de datos de MySQL

El patrón es el mismo en los proyectos que necesitan acceso a MySQL. En el archivo Program.cs, este código registra la base de datos:

builder.AddMySqlDataSource("mysqldb");

Una vez registrada la base de datos en el proyecto de consumo, puede interactuar con el origen de datos en cualquier momento que lo necesite mediante la inserción de dependencias:

app.MapGet("/catalog", async (MySqlConnection db) =>
{
    const string sql = """
        SELECT Id, Name, Description, Price
        FROM catalog
        """;

    // the db object is a connection to the MySQL database registered with AddMySqlDataSource
    return await db.QueryAsync<CatalogItem>(sql);
});

Configuración del componente de MySQL

El componente de MySQL admite las tres mismas opciones para administrar la configuración.

Cadenas de conexión

El archivo appsettings.json puede contener la cadena de conexión de la base de datos de MySQL:

{
  "ConnectionStrings": {
    "MySqConnection": "Server=myserver;Database=mysqldb;Uid=myuser;Pwd=mypassword"
  }
}

A continuación, en el proyecto, puede conectarse a la base de datos con la cadena de conexión mediante código similar al siguiente:

builder.AddMySqlDataSource("MySqConnection");

Proveedores de configuración

La clave Aspire:MySqlConnector se usa para configurar el componente de MySQL.

{
  "Aspire": {
    "MySqlConnector": {
      "ConnectionString": "Server=myserver;Database=mysqldb;Uid=myuser;Pwd=mypassword",
      "HealthChecks": true,
      "Tracing": false,
      "Metrics": false
    }
  }
}

Configuraciones insertadas

builder.AddMySqlDataSource("mysqldb", static settings => settings.HealthChecks = false);

Aprenda a inicializar la base de datos

La pila de .NET Aspire usa contenedores, obteniendo las ventajas de entornos coherentes e implementaciones sencillas. Un inconveniente es que los contenedores no tienen estado. Los datos o esquemas agregados a una base de datos se pierden cuando se destruye el contenedor. .NET Aspire proporciona maneras de inicializar las bases de datos con datos cuando crea sus contenedores.

Uso de volúmenes y scripts

La manera más sencilla de inicializar la base de datos es usar volúmenes y scripts de 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. Los scripts almacenados en estos volúmenes se ejecutan cuando se crea un contenedor, rellenando la base de datos con datos. El script puede ser un archivo de SQL que contenga los datos y el esquema que desee para la base de datos.

Por ejemplo, si tenía este script de SQL, almacenado en un archivo denominado postgres-backup.sql, en la carpeta Service.API/Seed:

CREATE TABLE catalog (
  Id INT PRIMARY KEY,
  Name VARCHAR(50),
  Description VARCHAR(255),
  Price DECIMAL(18, 2)
);

INSERT INTO catalog (Id, Name, Description, Price)
VALUES (1, 'Item 1', 'Description of item 1', 10.99),
      (2, 'Item 2', 'Description of item 2', 20.99),
      (3, 'Item 3', 'Description of item 3', 30.99);

En el host de la aplicación de la solución, puede enlazar la carpeta Service.API/Seed a la carpeta /docker-entrypoint-initdb.d del contenedor. Esta es una carpeta especial en el contenedor de PostgreSQL que ejecuta los scripts de SQL que encuentra cuando se crea el contenedor:

    var catalogDB = builder.AddPostgres("postgres")
      .WithPgAdmin()
      .WithEnvironment("POSTGRES_DB", "backendDB")
      .WithBindMount("../Service.API/Seed", "/docker-entrypoint-initdb.d")
      .AddDatabase("backendDB");

Incluso puede dividir los scripts de SQL en scripts de creación de esquemas e inicialización de datos. Si están incluidos en la carpeta Service.API/Seed, se ejecutan cuando .NET Aspire crea la base de datos.

Propagación de datos mediante Entity Framework Core

Para los componentes que admiten Entity Framework Core, puede inicializar la base de datos mediante la clase DbContext y las migraciones principales de Entity Framework. Este método usa código de C# para inicializar la base de datos. Sin embargo, esta propagación solo debe producirse durante el desarrollo o las pruebas, no en producción.

// Register DbContext class
builder.AddNpgsqlDbContext<CatalogContext>("sqldata");

var app = builder.Build();

app.MapDefaultEndpoints();

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

El código anterior comprueba el estado del entorno de la aplicación. Si está en desarrollo, el código recupera la clase CatalogContext y ejecuta el método EnsureCreated. Este método crea la base de datos y ejecuta las migraciones pendientes.

Para obtener más información sobre cómo inicializar los distintos componentes de base de datos, consulte la documentación de .NET Aspire.