Armazenar dados em bancos de dados compatíveis com SQL

Concluído

A pilha .NET Aspire foi concebida para o tornar mais produtivo e para o ajudar a criar aplicações Web robustas, escaláveis e seguras. Pode armazenar rapidamente dados relacionais estruturados adicionando um dos componentes suportados do Aspire .

Os componentes atuais do banco de dados compatível com SQL são:

  • Bases de Dados PostgreSQL
  • Bases de Dados SQL
  • Bancos de dados Oracle
  • Bases de Dados MySQL

Nota

A Microsoft pode adicionar suporte para outros sistemas de banco de dados e terceiros também podem contribuir, portanto, esta lista pode se expandir.

Nesta unidade, saiba mais sobre três desses componentes, quais bancos de dados têm suporte ao Entity Framework Core e como usá-los para armazenar e recuperar dados.

Como adicionar um componente de banco de dados ao seu projeto

Seja qual for o banco de dados escolhido, a abordagem para adicionar um componente de banco de dados .NET Aspire ao seu projeto é a mesma.

No projeto de host do aplicativo:

  • Instale o componente de hospedagem .NET Aspire no projeto de host do aplicativo.
  • Registre um banco de dados e crie um contêiner para ele no host do aplicativo da solução.
  • Passe uma referência para os projetos que precisam de acesso ao contêiner criado que hospeda o banco de dados.

Nos projetos que usam o banco de dados:

  • Adicione o componente .NET Aspire com um pacote NuGet aos projetos que exigem acesso a dados. Opcionalmente, se houver um componente .NET Core Entity Framework (EF), você poderá usá-lo.
  • Registre a fonte de dados, ou o contexto do banco de dados para EF, no arquivo Program.cs do projeto.
  • Use a injeção de dependência para injetar a fonte de dados em seus serviços.

Vamos examinar as especificidades de como executar essas etapas para cada um dos bancos de dados suportados.

Usando os componentes do .NET Aspire PostgreSQL

Os componentes do .NET Aspire PostgreSQL exigem alterações no projeto de host do aplicativo e em quaisquer microsserviços que usem os bancos de dados.

Configurando o host do aplicativo

Comece instalando o componente de hospedagem apropriado no host do aplicativo:

dotnet add package Aspire.Hosting.PostgreSQL --prerelease

Em seguida, para registrar um banco de dados e criar um contêiner para ele, adicione este código ao arquivo Program.cs do host do aplicativo:

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

Você também deve passar uma referência ao serviço de banco de dados para todos os projetos que o consomem:

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

Configurando os projetos que consomem

Para instalar o componente .NET Aspire PostgreSQL, use um comando como este em seus projetos do .NET Aspire :

dotnet add package Aspire.Npgsql --prerelease

Ou para usar o componente .NET Aspire PostgreSQL Entity Framework Core, use este comando:

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

Como alternativa, você pode usar o atalho Adicionar > componente .NET Aspire no Visual Studio para instalar o componente do gerenciador de pacotes NuGet:

Captura de tela mostrando o gerenciador de pacotes NuGet no Visual Studio exibindo componentes do .NET Aspire PostgreSQL.

Código no *. O arquivo Program.cs do projeto AppHost cria o banco de dados e o passa para os projetos que desejam usá-lo:

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

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

Alguns dos componentes de banco de dados do .NET Aspire também permitem que você crie um contêiner para ferramentas de gerenciamento de banco de dados. Para adicionar PgAdmin à sua solução para gerenciar o banco de dados PostgreSQL, use este código:

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

A vantagem de permitir que o .NET Aspire crie o contêiner é que você não precisa fazer nenhuma configuração para conectar o PgAdmin ao banco de dados PostgreSQL, é tudo automático.

Usando um banco de dados PostgreSQL

Em qualquer projeto onde você deseja usar o banco de dados, você adiciona uma fonte de dados para representar a conexão com o PostgreSQL. No ficheiro Program.cs, este código regista a base de dados:

builder.AddNpgsqlDataSource("postgresdb");

Ou para usar o componente Entity Framework Core, registre o contexto do banco de dados:

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

Depois que o banco de dados for registrado no projeto de consumo, você poderá interagir com a fonte de dados sempre que precisar usando a injeção de dependência:

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

Ou você pode recuperar o contexto YourDbContext do banco de dados para interagir com o banco de dados:

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

Configurando o componente PostgreSQL

A pilha do .NET Aspire tenta reduzir a quantidade de configuração que você precisa fazer. Usando a injeção de dependência e a descoberta de serviço, você pode acessar o banco de dados sem precisar configurar as cadeias de conexão em seus projetos.

Usar o projeto host do aplicativo para criar o contêiner de banco de dados e passá-lo como uma referência para os projetos, permite que os projetos de recebimento acessem o local do banco de dados, cadeias de conexão e portas. Não há necessidade de gerenciar variáveis de ambiente ou arquivos appsettings.json .

Mas, se você quiser, ou precisar de mais controle sobre como o banco de dados é configurado, há mais opções.

Usando uma cadeia de conexão

No projeto que requer o banco de dados, você usa uma cadeia de conexão para se conectar ao banco de dados. Essa abordagem é útil quando você precisa se conectar a um banco de dados que não está registrado no host do aplicativo.

builder.AddNpgsqlDataSource("NpgsqlConnectionString");

Em seguida, no arquivo de configuração, você pode adicionar a cadeia de conexão:

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

Usando provedores de configuração

O .NET Aspire tem uma funcionalidade de componentes que lhes permite suportar um Microsoft.Extensions.Configurationficheiro . O componente PostgreSQL suporta esse recurso e, por padrão, procura configurações usando a Aspire:Npgsql chave. Em projetos que usam appsettings.json, um exemplo de configuração pode ter esta aparência:

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

A configuração anterior está definindo a cadeia de conexão, habilitando verificações de integridade, rastreamento e métricas para o componente PostgreSQL. Você codifica, então, não precisa mais especificar a cadeia de conexão, basta usar builder.AddNpgsqlDataSource();.

Se você estiver usando o componente PostgreSQL Entity Framework Core, poderá usar a Aspire:Npgsql:EntityFrameworkCore:PostgreSQL chave para configurar o contexto do banco de dados:

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

Para obter mais informações sobre as opções de configuração do Entity Framework, consulte a documentação do .NET Aspire .

Usando delegados embutidos

A última opção é passar um configureSettings delegado embutido para o AddNpgsqlDataSource método. Este delegado permite que você defina as configurações para o componente de banco de dados diretamente com código:

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

Usando os componentes do Banco de dados SQL do .NET Aspire

O padrão anterior é o mesmo para o componente Banco de dados SQL. Você faz alterações no projeto de host do aplicativo e nos microsserviços que consomem o serviço de banco de dados.

Configurando o host do aplicativo

Para instalar o componente de hospedagem do banco de dados SQL, use este comando:

dotnet add package Aspire.Hosting.SqlServer --prerelease

Para registrar o contêiner e o banco de dados, adicione este código ao arquivo Program.cs do host do aplicativo:

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

Em seguida, passe uma referência ao serviço de banco de dados para todos os projetos que o consomem:

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

Configurando os projetos que consomem

Para instalar o componente Banco de dados SQL do .NET Aspire , use um comando como este em seus projetos do .NET Aspire :

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

Ou para usar o componente .NET Aspire SqlServer Entity Framework Core, use este comando:

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

Esses pacotes NuGet também podem ser adicionados usando o atalho Add > .NET Aspire Component no Visual Studio.

O *. O código de arquivo Program.cs do projeto AppHost para acessar o banco de dados é semelhante ao exemplo do PostgreSQL:

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

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

Usando um banco de dados do SQL Server

Nos projetos que precisam de acesso SQL, no arquivo Program.cs , esse código registra o contexto do banco de dados do Entity Framework:

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

Depois que o banco de dados é registrado no projeto de consumo, você pode interagir com o contexto YourDbContext do banco de dados usando a injeção de dependência. Este código de exemplo recupera previsões meteorológicas de um banco de dados e seleciona uma aleatoriamente para retornar:

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

Configurando o componente SQL Server

Como antes, se você usar o mesmo nome de banco de dados no host do aplicativo e no projeto consumidor, não precisará configurar a conexão entre o banco de dados do SQL Server e os projetos. O componente .NET Aspire SQL Server também oferece suporte a outras maneiras de configurar o componente.

Usando provedores de configuração

O componente SQL Server também oferece suporte ao Microsoft.Extensions.Configuration. Por padrão, ele procura configurações usando a Aspire:SqlServer:SqlClient chave. Em projetos que usam appsettings.json, um exemplo de configuração pode ter esta aparência:

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

Usando configurações em linha

Quando você adiciona o componente SQL Server, você pode passar um configureSettings delegado embutido para o AddSqlServerClient método. Este delegado permite que você defina as configurações para o componente de banco de dados diretamente com código:

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

Você pode passar qualquer uma das opções suportadas:

  • ConnectionString: A cadeia de conexão do banco de dados do SQL Server
  • HealthChecks: Um valor booleano que indica se a verificação de integridade do banco de dados está habilitada
  • Tracing: Um valor booleano que indica se o rastreamento OpenTelemetry está habilitado
  • Metrics: Um valor booleano que indica se as métricas OpenTelemetry estão habilitadas

Conectar-se a vários bancos de dados

O componente SQL Server dá suporte a várias conexões por meio de instâncias nomeadas. Por exemplo, você pode se conectar a dois bancos de dados SQL Server diferentes no mesmo projeto:

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

Usando essa configuração, você pode se conectar aos dois bancos de dados diferentes no mesmo projeto:

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

Usando o componente MySQL

Para instalar o componente .NET Aspire MySQL, use um comando como este em seus projetos .NET Aspire que exigem acesso a dados:

dotnet add package Aspire.MySqlConnector --prerelease

Ou use o atalho Adicionar > componente .NET Aspire no Visual Studio para instalar o componente do gerenciador de pacotes NuGet.

O *. O código de arquivo Program.cs do projeto AppHost para acessar o banco de dados é semelhante ao exemplo do PostgreSQL:

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

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

Como o componente PostgreSQL, o componente MySQL também permite criar um contêiner para ferramentas de gerenciamento de banco de dados. O exemplo anterior adiciona PhpMyAdmin à solução.

Usando um banco de dados MySQL

O padrão é o mesmo nos projetos que precisam de acesso ao MySQL. No ficheiro Program.cs, este código regista a base de dados:

builder.AddMySqlDataSource("mysqldb");

Depois que o banco de dados for registrado no projeto de consumo, você poderá interagir com a fonte de dados sempre que precisar usando a injeção de dependência:

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

Configurando o componente MySQL

O componente MySQL suporta as mesmas três opções para gerenciar a configuração.

Cadeias de ligação

O arquivo appsettings.json pode conter a cadeia de conexão para o banco de dados MySQL:

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

Em seguida, em seu projeto, você pode se conectar ao banco de dados com a cadeia de conexão usando um código como este:

builder.AddMySqlDataSource("MySqConnection");

Provedores de configuração

A Aspire:MySqlConnector chave é usada para configurar o componente MySQL.

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

Configurações em linha

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

Saiba como semear a sua base de dados

A pilha do .NET Aspire usa contêineres, obtendo as vantagens de ambientes consistentes e implantações fáceis. Uma desvantagem é que os contêineres são apátridas. Todos os dados ou esquemas adicionados a um banco de dados são perdidos quando o contêiner é destruído. O .NET Aspire fornece maneiras de semear seus bancos de dados com dados quando cria seus contêineres.

Usando volumes e scripts

A maneira mais simples de semear seu banco de dados é usar volumes e scripts SQL. Os volumes podem armazenar dados para vários contêineres ao mesmo tempo, oferecem alto desempenho e são fáceis de fazer backup ou migrar. Os scripts armazenados nesses volumes são executados quando um contêiner é criado, preenchendo o banco de dados com dados. O script pode ser um arquivo SQL que contém os dados e o esquema desejados para seu banco de dados.

Por exemplo, se você tinha esse script SQL, armazenado em um arquivo chamado postgres-backup.sql, na pasta 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);

No host do aplicativo da solução, você pode vincular a pasta Service.API/Seed à pasta /docker-entrypoint-initdb.d do contêiner. Esta pasta é uma pasta especial no contêiner PostgreSQL que executa quaisquer scripts SQL encontrados quando o contêiner é criado:

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

Você pode até dividir os scripts SQL em scripts de criação de esquema e propagação de dados. Se todos eles estiverem contidos na pasta Service.API/Seed, eles serão executados quando o .NET Aspire criar o banco de dados.

Semeadura de dados usando o Entity Framework Core

Para os componentes que suportam o Entity Framework Core, você pode semear seu banco de dados usando as migrações de núcleo de classe e Entity DbContext Framework. Esse método usa código C# para semear o banco de dados. No entanto, essa semeadura só deve acontecer durante o desenvolvimento ou teste, não na produção.

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

O código acima verifica o estado do ambiente do aplicativo. Se estiver em desenvolvimento, o código recupera a CatalogContext classe e executa o EnsureCreated método. Esse método cria o banco de dados e executa todas as migrações pendentes.

Para obter mais informações sobre como semear os diferentes componentes do banco de dados, consulte a documentação do .NET Aspire .