Partilhar via


.NET Aspire Azure PostgreSQL Entity Framework Core integração

Inclui: integração de serviços de alojamento e Client outras integrações

Azure Database for PostgreSQL—Flexible Server é um serviço de banco de dados relacional baseado no mecanismo de banco de dados de código aberto Postgres. É um banco de dados como serviço totalmente gerenciado que pode lidar com cargas de trabalho de missão crítica com desempenho previsível, segurança, alta disponibilidade e escalabilidade dinâmica. A integração .NET AspireAzurePostgreSQL fornece uma maneira de se conectar a bancos de dados AzurePostgreSQL existentes ou criar novas instâncias a partir de .NET com a imagem de contêiner docker.io/library/postgres.

Integração de hospedagem

A integração de hospedagem .NET AspireAzurePostgreSQL modela um servidor e banco de dados PostgreSQL flexíveis conforme os tipos AzurePostgresFlexibleServerResource e AzurePostgresFlexibleServerDatabaseResource. Outros tipos que estão inerentemente disponíveis na integração de hospedagem são representados nos seguintes recursos:

Para aceder a esses tipos e APIs para expressá-los como recursos no seu projeto de hospedeiro da aplicação , instale o pacote NuGet 📦Aspire.Hosting.Azure.PostgreSQL.

dotnet add package Aspire.Hosting.Azure.PostgreSQL

Para obter mais informações, consulte dotnet add package.

A integração de alojamento AzurePostgreSQL depende do pacote NuGet 📦Aspire.Hosting.PostgreSQL, estendendo-o para oferecer suporte a Azure. Tudo o que tu podes fazer com a integração .NET AspirePostgreSQL e a integração .NET AspirePostgreSQLEntity Framework Core, também podes fazer com esta integração.

Adicionar AzurePostgreSQL recurso do servidor

Depois de instalar a integração de hospedagem .NET AspireAzurePostgreSQL, chame o método de extensão AddAzurePostgresFlexibleServer em seu projeto de host de aplicativo:

var builder = DistributedApplication.CreateBuilder(args);

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

var exampleProject = builder.AddProject<Projects.ExampleProject>()
                            .WithReference(postgresdb);

A chamada anterior para AddAzurePostgresFlexibleServer configura o recurso de servidor PostgreSQL para ser implantado como um recurso AzurePostgres flexível Server.

Importante

Por padrão, AddAzurePostgresFlexibleServer configura a autenticação do Microsoft Entra ID. Isso requer alterações nos aplicativos que precisam se conectar a esses recursos. Para obter mais informações, consulte a integração Client.

Dica

Quando você chama AddAzurePostgresFlexibleServer, ele chama implicitamente AddAzureProvisioning—que adiciona suporte para gerar recursos de Azure dinamicamente durante a inicialização do aplicativo. O aplicativo deve configurar a assinatura e o local apropriados. Para mais informações, consulte Configuração: Provisionamento local.

Provisionamento automatizado com Bicep

Se és novo no Bicep, é uma linguagem de domínio específico para a definição de recursos Azure. Com .NET.NET Aspire, você não precisa escrever Bicep manualmente, porque as APIs de provisionamento geram Bicep para você. Ao publicares a tua aplicação, o Bicep gerado é exibido juntamente com o ficheiro de manifesto. Ao adicionar um recurso AzurePostgreSQL, o seguinte Bicep é gerado:

@description('The location for the resource(s) to be deployed.')
param location string = resourceGroup().location

param principalId string

param principalType string

param principalName string

resource postgres_flexible 'Microsoft.DBforPostgreSQL/flexibleServers@2024-08-01' = {
  name: take('postgresflexible-${uniqueString(resourceGroup().id)}', 63)
  location: location
  properties: {
    authConfig: {
      activeDirectoryAuth: 'Enabled'
      passwordAuth: 'Disabled'
    }
    availabilityZone: '1'
    backup: {
      backupRetentionDays: 7
      geoRedundantBackup: 'Disabled'
    }
    highAvailability: {
      mode: 'Disabled'
    }
    storage: {
      storageSizeGB: 32
    }
    version: '16'
  }
  sku: {
    name: 'Standard_B1ms'
    tier: 'Burstable'
  }
  tags: {
    'aspire-resource-name': 'postgres-flexible'
  }
}

resource postgreSqlFirewallRule_AllowAllAzureIps 'Microsoft.DBforPostgreSQL/flexibleServers/firewallRules@2024-08-01' = {
  name: 'AllowAllAzureIps'
  properties: {
    endIpAddress: '0.0.0.0'
    startIpAddress: '0.0.0.0'
  }
  parent: postgres_flexible
}

resource postgres_flexible_admin 'Microsoft.DBforPostgreSQL/flexibleServers/administrators@2024-08-01' = {
  name: principalId
  properties: {
    principalName: principalName
    principalType: principalType
  }
  parent: postgres_flexible
  dependsOn: [
    postgres_flexible
    postgreSqlFirewallRule_AllowAllAzureIps
  ]
}

output connectionString string = 'Host=${postgres_flexible.properties.fullyQualifiedDomainName};Username=${principalName}'

O Bicep anterior é um módulo que provisiona um servidor AzurePostgreSQL flexível com os seguintes padrões:

  • authConfig: A configuração de autenticação do servidor PostgreSQL. O padrão é ActiveDirectoryAuth ativado e PasswordAuth desabilitado.
  • availabilityZone: A zona de disponibilidade do servidor PostgreSQL. A predefinição é 1.
  • backup: A configuração de backup do servidor PostgreSQL. O padrão é BackupRetentionDays definido como 7 e GeoRedundantBackup definido como Disabled.
  • highAvailability: A configuração de alta disponibilidade do servidor PostgreSQL. A predefinição é Disabled.
  • storage: A configuração de armazenamento do servidor PostgreSQL. O padrão é StorageSizeGB definido como 32.
  • version: A versão do servidor PostgreSQL. A predefinição é 16.
  • sku: O SKU do servidor PostgreSQL. A predefinição é Standard_B1ms.
  • tags: Tags do servidor PostgreSQL. O padrão é aspire-resource-name definido como o nome do recurso Aspire, neste caso postgres-flexible.

Além do servidor PostgreSQL flexível, ele também provisiona uma regra de Firewall Azure para permitir todos os Azure endereços IP. Finalmente, um administrador é criado para o servidor PostgreSQL e a cadeia de conexão é gerada como uma variável de saída. O Bíceps gerado é um ponto de partida e pode ser personalizado para atender às suas necessidades específicas.

Personalizar a infraestrutura de provisionamento

Todos os recursos .NET AspireAzure são subclasses do tipo AzureProvisioningResource. Este tipo permite a personalização do Bicep gerado, fornecendo uma API fluente para configurar os recursos Azure utilizando a API ConfigureInfrastructure<T>(IResourceBuilder<T>, Action<AzureResourceInfrastructure>). Por exemplo, você pode configurar o kind, consistencyPolicy, locationse muito mais. O exemplo a seguir demonstra como personalizar o recurso de servidor PostgreSQL:

builder.AddAzureCosmosDB("cosmos-db")
    .ConfigureInfrastructure(infra =>
    {
        var flexibleServer = infra.GetProvisionableResources()
                                  .OfType<PostgreSqlFlexibleServer>()
                                  .Single();

        flexibleServer.Sku = new PostgreSqlFlexibleServerSku
        {
            Tier = PostgreSqlFlexibleServerSkuTier.Burstable,
        };
        flexibleServer.HighAvailability = new PostgreSqlFlexibleServerHighAvailability
        {
            Mode = PostgreSqlFlexibleServerHighAvailabilityMode.ZoneRedundant,
            StandbyAvailabilityZone = "2",
        };
        flexibleServer.Tags.Add("ExampleKey", "Example value");
    });

O código anterior:

Há muito mais opções de configuração disponíveis para personalizar o recurso de servidor PostgreSQL flexível. Para obter mais informações, consulte Azure.Provisioning.PostgreSql e Azure. Personalização do provisionamento.

Conectar-se a um servidor flexível AzurePostgreSQL existente

Você pode ter um servidor existente AzurePostgreSQL flexível ao qual deseja se conectar. Em vez de representar um novo recurso de servidor AzurePostgreSQL flexível, você pode adicionar uma cadeia de conexão ao host do aplicativo. Para adicionar uma conexão a um servidor existente AzurePostgreSQL flexível, chame o método AddConnectionString:

var builder = DistributedApplication.CreateBuilder(args);

var postgres = builder.AddConnectionString("postgres");

builder.AddProject<Projects.WebApplication>("web")
       .WithReference(postgres);

// After adding all resources, run the app...

Observação

As cadeias de conexão são usadas para representar uma ampla gama de informações de conexão, incluindo conexões de banco de dados, agentes de mensagens, URIs de ponto de extremidade e outros serviços. Na nomenclatura .NET.NET Aspire, o termo "cadeia de conexão" é usado para representar qualquer tipo de informação de conexão.

A cadeia de conexão é configurada nas definições do anfitrião da aplicação, normalmente na secção Segredos do Usuário, na secção ConnectionStrings. O host do aplicativo injeta essa cadeia de conexão como uma variável de ambiente em todos os recursos dependentes, por exemplo:

{
    "ConnectionStrings": {
        "postgres": "Server=<PostgreSQL-server-name>.postgres.database.azure.com;Database=<database-name>;Port=5432;Ssl Mode=Require;User Id=<username>;"
    }
}

O recurso dependente pode acessar a cadeia de conexão injetada chamando o método GetConnectionString e passando o nome da conexão como parâmetro, neste caso "postgres". A API GetConnectionString é uma abreviação de IConfiguration.GetSection("ConnectionStrings")[name].

Executar AzurePostgreSQL recurso como um contêiner

A integração de hospedagem AzurePostgreSQL suporta a execução do servidor PostgreSQL como um contêiner local. Isso é benéfico para situações em que você deseja executar o servidor PostgreSQL localmente para fins de desenvolvimento e teste, evitando a necessidade de provisionar um recurso Azure ou conectar-se a um servidor AzurePostgreSQL existente.

Para executar o servidor PostgreSQL como um contêiner, chame o método RunAsContainer:

var builder = DistributedApplication.CreateBuilder(args);

var postgres = builder.AddAzurePostgresFlexibleServer("postgres")
                      .RunAsContainer();

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

var exampleProject = builder.AddProject<Projects.ExampleProject>()
                            .WithReference(postgresdb);

O código anterior configura um recurso AzurePostgreSQL Flexible Server para ser executado localmente em um contêiner.

Dica

O método RunAsContainer é útil para o desenvolvimento local e testes. A API expõe um delegado opcional que permite personalizar a configuração de PostgresServerResource subjacente. Por exemplo, pode-se adicionar o pgAdmin e o pgWeb, adicionar um volume de dados ou montagem de diretório de dados, e adicionar uma montagem de diretório de inicialização. Para obter mais informações, consulte a seção .NET AspirePostgreSQL de integração de hospedagem.

Configurar o servidor AzurePostgreSQL para usar a autenticação de senha

Por padrão, o servidor AzurePostgreSQL está configurado para usar a autenticação do Microsoft Entra ID . Se você quiser usar a autenticação de senha, você pode configurar o servidor para usar a autenticação de senha chamando o método WithPasswordAuthentication:

var builder = DistributedApplication.CreateBuilder(args);

var username = builder.AddParameter("username", secret: true);
var password = builder.AddParameter("password", secret: true);

var postgres = builder.AddAzurePostgresFlexibleServer("postgres")
                      .WithPasswordAuthentication(username, password);

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

var exampleProject = builder.AddProject<Projects.ExampleProject>()
                            .WithReference(postgresdb);

O código anterior configura o servidor AzurePostgreSQL para usar a autenticação de senha. Os parâmetros username e password são adicionados ao host do aplicativo como parâmetros, e o método WithPasswordAuthentication é chamado para configurar o servidor AzurePostgreSQL para usar a autenticação de senha. Para obter mais informações, consulte Parâmetros externos.

Client integração

Para começar com a integração do cliente .NET AspirePostgreSQLEntity Framework Core, instale o pacote NuGet 📦Aspire.Npgsql.EntityFrameworkCore.PostgreSQL no projeto que consome o cliente, ou seja, o projeto para a aplicação que utiliza o cliente PostgreSQL. A integração do cliente .NET AspirePostgreSQLEntity Framework Core regista as instâncias de subclasse DbContext desejadas, que pode usar para interagir com PostgreSQL.

dotnet add package Aspire.Npgsql.EntityFrameworkCore.PostgreSQL

Adicionar contexto de banco de dados Npgsql

No ficheiro de Program.cs do seu projeto cliente, chame o método de extensão AddNpgsqlDbContext em qualquer IHostApplicationBuilder para registar a sua subclasse DbContext para que seja usada através do contentor de injeção de dependência. O método usa um parâmetro de nome de conexão.

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

Dica

O parâmetro connectionName deve corresponder ao nome usado ao adicionar o recurso de servidor PostgreSQL no projeto de host do aplicativo. Para obter mais informações, veja Adicionar recurso de servidor PostgreSQL.

Depois de adicionar YourDbContext ao construtor, você pode obter a instância YourDbContext usando a injeção de dependência. Por exemplo, para recuperar seu objeto de fonte de dados de um serviço de exemplo, defina-o como um parâmetro de construtor e verifique se a classe ExampleService está registrada com o contêiner de injeção de dependência:

public class ExampleService(YourDbContext context)
{
    // Use context...
}

Para mais informações sobre injeção de dependência, consulte .NET injeção de dependência.

Melhore um contexto de base de dados Npgsql

Você pode preferir usar o método padrão do Entity Framework para obter um contexto de banco de dados e adicioná-lo ao contêiner de injeção de dependência:

builder.Services.AddDbContext<YourDbContext>(options =>
    options.UseNpgsql(builder.Configuration.GetConnectionString("postgresdb")
        ?? throw new InvalidOperationException("Connection string 'postgresdb' not found.")));

Observação

O nome da cadeia de conexão que você passa para o método GetConnectionString deve corresponder ao nome usado ao adicionar o recurso de servidor PostgreSQL no projeto de host do aplicativo. Para obter mais informações, veja Adicionar recurso de servidor PostgreSQL.

Você tem mais flexibilidade ao criar o contexto do banco de dados dessa maneira, por exemplo:

  • Você pode reutilizar o código de configuração existente para o contexto do banco de dados sem reescrevê-lo para .NET.NET Aspire.
  • Você pode usar Entity Framework Core interceptores para modificar operações de banco de dados.
  • Você pode optar por não usar a agregação de contexto Entity Framework Core, que pode ter um desempenho melhor em algumas circunstâncias.

Se utilizar este método, pode melhorar o contexto do banco de dados com retries no estilo de .NET.NET Aspire, verificações de estado, registo e recursos de telemetria chamando o método EnrichNpgsqlDbContext:

builder.EnrichNpgsqlDbContext<YourDbContext>(
    configureSettings: settings =>
    {
        settings.DisableRetry = false;
        settings.CommandTimeout = 30;
    });

O parâmetro settings é uma instância da classe NpgsqlEntityFrameworkCorePostgreSQLSettings.

Configuração

A integração .NET AspirePostgreSQLEntity Framework Core fornece várias abordagens e opções de configuração para atender aos requisitos e convenções do seu projeto.

Usar uma cadeia de conexão

Ao usar uma cadeia de conexão da seção de configuração ConnectionStrings, você fornece o nome da cadeia de conexão ao chamar o método AddNpgsqlDbContext:

builder.AddNpgsqlDbContext<MyDbContext>("pgdb");

A cadeia de conexão é recuperada da seção de configuração ConnectionStrings:

{
  "ConnectionStrings": {
    "pgdb": "Host=myserver;Database=test"
  }
}

O EnrichNpgsqlDbContext não usará a seção de configuração ConnectionStrings, pois espera que um DbContext seja registrado no ponto em que é chamado.

Para obter mais informações, consulte o ConnectionString.

Usar provedores de configuração

A integração .NET AspirePostgreSQLEntity Framework Core suporta Microsoft.Extensions.Configuration. Ele carrega o NpgsqlEntityFrameworkCorePostgreSQLSettings de arquivos de configuração, como appsettings.json, usando a chave Aspire:Npgsql:EntityFrameworkCore:PostgreSQL. Se você configurou suas configurações na seção Aspire:Npgsql:EntityFrameworkCore:PostgreSQL, você pode simplesmente chamar o método sem passar nenhum parâmetro.

O exemplo a seguir mostra um arquivo appsettings.json que configura algumas das opções disponíveis:

{
  "Aspire": {
    "Npgsql": {
      "EntityFrameworkCore": {
        "PostgreSQL": {
          "ConnectionString": "Host=myserver;Database=postgresdb",
          "DisableHealthChecks": true,
          "DisableTracing": true
        }
      }
    }
  }
}

Para o esquema completo de integração do cliente PostgreSQLEntity Framework CoreJSON, consulte Aspire.Npgsql.EntityFrameworkCore.PostgreSQL/ConfigurationSchema.json.

Usar delegados integrados

Você também pode passar o delegado Action<NpgsqlEntityFrameworkCorePostgreSQLSettings> para configurar algumas ou todas as opções integradas, por exemplo, para definir o ConnectionString:

builder.AddNpgsqlDbContext<YourDbContext>(
    "pgdb",
    static settings => settings.ConnectionString = "<YOUR CONNECTION STRING>");

Configurar várias classes DbContext

Se quiser registar mais de um DbContext com configurações diferentes, pode usar o nome da seção de configuração $"Aspire:Npgsql:EntityFrameworkCore:PostgreSQL:{typeof(TContext).Name}". A configuração json seria semelhante a:

{
  "Aspire": {
    "Npgsql": {
      "EntityFrameworkCore": {
        "PostgreSQL": {
          "ConnectionString": "<YOUR CONNECTION STRING>",
          "DisableHealthChecks": true,
          "DisableTracing": true,
          "AnotherDbContext": {
            "ConnectionString": "<ANOTHER CONNECTION STRING>",
            "DisableTracing": false
          }
        }
      }
    }
  }
}

Em seguida, chamar o método AddNpgsqlDbContext com o tipo de parâmetro AnotherDbContext carregaria as configurações da seção Aspire:Npgsql:EntityFrameworkCore:PostgreSQL:AnotherDbContext.

builder.AddNpgsqlDbContext<AnotherDbContext>();

Client verificações de saúde de integração

Por padrão, .NET.NET Aspireintegrações de cliente têm verificações de integridade habilitadas para todos os serviços. Da mesma forma, muitas integrações de alojamento .NET.NET Aspire também ativam pontos finais de verificação de integridade. Para mais informações, consulte:

Por padrão, as integrações .NET AspirePostgreSQLEntity Framework Core lidam com o seguinte:

  • Adiciona o DbContextHealthCheck, que chama o método EF Core de CanConnectAsync. O nome da verificação de saúde é o nome do tipo de TContext.
  • Integra-se com o endpoint HTTP /health, que especifica que todas as verificações de estado registadas devem passar para que a aplicação seja considerada pronta a aceitar tráfego

Observabilidade e telemetria

.NET .NET Aspire integrações configuram automaticamente o registo, rastreamento e métricas, que às vezes são conhecidos como os pilares da observabilidade. Para obter mais informações sobre observabilidade e telemetria de integração, consulte Visão geral de integrações .NET.NET Aspire. Dependendo do serviço de suporte, algumas integrações podem suportar apenas alguns desses recursos. Por exemplo, algumas integrações suportam registro em log e rastreamento, mas não métricas. Os recursos de telemetria também podem ser desativados usando as técnicas apresentadas na secção de configuração .

Registo

A integração .NET AspirePostgreSQLEntity Framework Core usa as seguintes categorias de Log:

  • Microsoft.EntityFrameworkCore.ChangeTracking
  • Microsoft.EntityFrameworkCore.Database.Command
  • Microsoft.EntityFrameworkCore.Database.Connection
  • Microsoft.EntityFrameworkCore.Database.Transaction
  • Microsoft.EntityFrameworkCore.Migrations
  • Microsoft.EntityFrameworkCore.Infrastructure
  • Microsoft.EntityFrameworkCore.Migrations
  • Microsoft.EntityFrameworkCore.Model
  • Microsoft.EntityFrameworkCore.Model.Validation
  • Microsoft.EntityFrameworkCore.Query
  • Microsoft.EntityFrameworkCore.Update

Rastreio

A integração .NET AspirePostgreSQLEntity Framework Core emitirá as seguintes atividades de rastreio utilizando OpenTelemetry:

  • Npgsql

Métricas

A integração .NET AspirePostgreSQLEntity Framework Core emitirá as seguintes métricas usando OpenTelemetry:

  • Microsoft.EntityFrameworkCore:

    • ec_Microsoft_EntityFrameworkCore_active_db_contexts
    • ec_Microsoft_EntityFrameworkCore_total_queries
    • ec_Microsoft_EntityFrameworkCore_queries_per_second
    • ec_Microsoft_EntityFrameworkCore_total_save_changes
    • ec_Microsoft_EntityFrameworkCore_save_changes_per_second
    • ec_Microsoft_EntityFrameworkCore_compiled_query_cache_hit_rate
    • ec_Microsoft_Entity_total_execution_strategy_operation_failures
    • ec_Microsoft_E_execution_strategy_operation_failures_per_second
    • ec_Microsoft_EntityFramew_total_optimistic_concurrency_failures
    • ec_Microsoft_EntityF_optimistic_concurrency_failures_per_second
  • Npgsql:

    • ec_Npgsql_bytes_written_per_second
    • ec_Npgsql_bytes_read_per_second
    • ec_Npgsql_commands_per_second
    • ec_Npgsql_total_commands
    • ec_Npgsql_current_commands
    • ec_Npgsql_failed_commands
    • ec_Npgsql_prepared_commands_ratio
    • ec_Npgsql_connection_pools
    • ec_Npgsql_multiplexing_average_commands_per_batch
    • ec_Npgsql_multiplexing_average_write_time_per_batch

Adicionar cliente Npgsql autenticado Azure

Por defeito, ao chamar AddAzurePostgresFlexibleServer na integração de hospedagem PostgreSQL, é necessário o pacote NuGet 📦Azure.Identity para ativar a autenticação:

dotnet add package Azure.Identity

A conexão PostgreSQL pode ser consumida através da integração do cliente e Azure.Identity:

builder.AddNpgsqlDbContext<YourDbContext>(
    "postgresdb", 
    configureDataSourceBuilder: (dataSourceBuilder) =>
{
    if (!string.IsNullOrEmpty(dataSourceBuilder.ConnectionStringBuilder.Password))
    {
        return;
    }

    dataSourceBuilder.UsePeriodicPasswordProvider(async (_, ct) =>
    {
        var credentials = new DefaultAzureCredential();
        var token = await credentials.GetTokenAsync(
            new TokenRequestContext([
                "https://ossrdbms-aad.database.windows.net/.default"
            ]), ct);

        return token.Token;
    },
    TimeSpan.FromHours(24),
    TimeSpan.FromSeconds(10));
});

O trecho de código anterior demonstra como usar a classe DefaultAzureCredential do pacote Azure.Identity para autenticar com o Microsoft Entra ID e recuperar um token para se conectar à base de dados PostgreSQL. O método UsePeriodicPasswordProvider é utilizado para fornecer o token ao builder da string de conexão.

Ver também