.NET AspireAzurePostgreSQLEntity Framework Core 集成

包含:托管集成已包含 - Client 集成已包含Client 集成

Azure 数据库 for PostgreSQL(灵活 Server)是基于开源 Postgres 数据库引擎的关系数据库服务。 它是一种完全托管的数据库即服务,可以处理具有可预测性能、安全性、高可用性和动态可伸缩性的任务关键型工作负荷。 .NET AspireAzurePostgreSQL 集成提供了一种连接到现有 AzurePostgreSQL 数据库的方法,或者使用 .NET从 docker.io/library/postgres 创建新实例。

托管集成

托管集成 .NET AspireAzurePostgreSQL 将 PostgreSQL 灵活服务器和数据库建模为 AzurePostgresFlexibleServerResourceAzurePostgresFlexibleServerDatabaseResource 类型。 托管集成中固有可用的其他类型的表示在以下资源中:

若要在 应用主机 项目中将这些类型和 API 表示为资源,请安装 📦Aspire.Hosting.Azure.PostgreSQL NuGet 包:

dotnet add package Aspire.Hosting.Azure.PostgreSQL

有关详细信息,请查看 dotnet add package

托管集成AzurePostgreSQL 依赖于 📦Aspire.Hosting.PostgreSQL NuGet 包,并将其扩展以支持 Azure。 你可以使用 .NET AspirePostgreSQL 集成.NET AspirePostgreSQLEntity Framework Core 集成 所能做的所有事情,也可以在此集成中完成。

添加 AzurePostgreSQL 服务器资源

安装 .NET AspireAzurePostgreSQL 托管集成后,请在应用主机项目中调用 AddAzurePostgresFlexibleServer 扩展方法:

var builder = DistributedApplication.CreateBuilder(args);

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

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

上述对 AddAzurePostgresFlexibleServer 的调用将 PostgreSQL 服务器资源配置为 AzurePostgres 的灵活 Server

重要

默认情况下,AddAzurePostgresFlexibleServer 配置 Microsoft Entra ID 身份验证。 这需要更改需要连接到这些资源的应用程序。 有关详细信息,请参阅 Client 整合

提示

调用 AddAzurePostgresFlexibleServer时,它会隐式调用 AddAzureProvisioning,这增加了在应用启动期间动态生成 Azure 资源的支持。 应用必须配置相应的订阅和位置。 有关详细信息,请参阅 本地预配:配置

预配生成的 Bicep

如果你不熟悉 Bicep,它是一种领域专用语言,用于定义 Azure 资源。 使用 .NET.NET Aspire时,无需手动编写 Bicep,因为预配 API 会为你生成 Bicep。 发布应用时,生成的 Bicep 文件将与清单文件一同输出。 添加 AzurePostgreSQL 资源时,会生成以下 Bicep 代码段:

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

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
}

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

output name string = postgres_flexible.name

前面的 Bicep 是预配灵活服务器资源的模块 AzurePostgreSQL 。 此外,在单独的模块中为 Azure 资源创建角色分配:

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

param postgres_flexible_outputs_name string

param principalType string

param principalId string

param principalName string

resource postgres_flexible 'Microsoft.DBforPostgreSQL/flexibleServers@2024-08-01' existing = {
  name: postgres_flexible_outputs_name
}

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

除了 PostgreSQL 灵活服务器,它还预配 Azure 防火墙规则以允许所有 Azure IP 地址。 最后,将为 PostgreSQL 服务器创建管理员,连接字符串将输出为输出变量。 生成的 Bicep 作为起点,受 C# 中资源配置基础设施更改的影响。 直接对 Bicep 文件的自定义项所做的更改将被覆盖,因此请通过 C# 预配 API 进行更改,以确保它们反映在生成的文件中。

自定义预配基础结构

所有 .NET AspireAzure 资源都是 AzureProvisioningResource 类型的子类。 此类型通过提供一个流畅的 API,使用 Azure API 对 ConfigureInfrastructure<T>(IResourceBuilder<T>, Action<AzureResourceInfrastructure>) 资源进行配置,从而实现对生成的 Bicep 的自定义。 例如,可以配置 kindconsistencyPolicylocations等。 以下示例演示如何自定义 PostgreSQL 服务器资源:

builder.AddAzurePostgresFlexibleServer("postgres")
    .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");
    });

前面的代码:

还有更多配置选项可用于自定义 PostgreSQL 灵活服务器资源。 有关详细信息,请参阅 Azure.Provisioning.PostgreSqlAzure。预配自定义

连接到现有 AzurePostgreSQL 灵活服务器

你可能已有一个现有的灵活服务器 AzurePostgreSQL 并希望连接到它。 链接调用以标注你的 AzurePostgresFlexibleServerResource 是现有资源:

var builder = DistributedApplication.CreateBuilder(args);

var existingPostgresName = builder.AddParameter("existingPostgresName");
var existingPostgresResourceGroup = builder.AddParameter("existingPostgresResourceGroup");

var postgres = builder.AddAzurePostgresFlexibleServer("postgres")
                      .AsExisting(existingPostgresName, existingPostgresResourceGroup);

builder.AddProject<Projects.ExampleProject>()
       .WithReference(postgres);

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

有关将 AzurePostgreSQL 灵活服务器资源视为现有资源的详细信息,请参阅 “使用现有 Azure 资源”。

注意

或者,可以向应用主机添加连接字符串,而不是表示 AzurePostgreSQL 灵活服务器资源。 此方法属于弱类型,不适用于角色分配或基础结构自定义。 有关详细信息,请参阅 添加包含连接字符串的现有 Azure 资源

以容器身份运行 AzurePostgreSQL 资源

托管集成 AzurePostgreSQL 支持将 PostgreSQL 服务器作为本地容器运行。 这适用于想要在本地运行 PostgreSQL 服务器以进行开发和测试的情况,避免需要预配 Azure 资源或连接到现有 AzurePostgreSQL 服务器。

若要将 PostgreSQL 服务器作为容器运行,请调用 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);

前面的代码将 AzurePostgreSQL 灵活 Server 资源配置为在容器中本地运行。

提示

RunAsContainer 方法可用于本地开发和测试。 API 提供一个可选委托,允许您自定义底层的 PostgresServerResource 配置。 例如,您可以添加 pgAdmin 和 pgWeb,增加数据卷或数据绑定挂载,还可以增加初始化绑定挂载。 有关详细信息,请参阅 .NET AspirePostgreSQL 托管集成 部分。

将 AzurePostgreSQL 服务器配置为使用密码身份验证

默认情况下,AzurePostgreSQL 服务器配置为使用 Microsoft Entra ID 身份验证。 如果要使用密码身份验证,可以通过调用 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);

前面的代码将 AzurePostgreSQL 服务器配置为使用密码身份验证。 usernamepassword 参数作为参数添加到应用主机,调用 WithPasswordAuthentication 方法以配置 AzurePostgreSQL 服务器以使用密码身份验证。 有关详细信息,请参阅 外部参数

Client 集成

若要开始使用 .NET AspirePostgreSQLEntity Framework Core 客户端集成,请安装 📦Aspire..AzureNpgsql.EntityFrameworkCore。PostgreSQL 客户端使用项目中的 NuGet 包,即使用 PostgreSQL 客户端的应用程序的项目。 .NET AspirePostgreSQLEntity Framework Core 客户端集成注册您所需的 DbContext 子类实例,可用于与 PostgreSQL进行交互。

dotnet add package Aspire.Azure.Npgsql.EntityFrameworkCore.PostgreSQL

可以通过使用客户端集成来消耗PostgreSQL连接,方法是调用AddAzureNpgsqlDataSource

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

提示

connectionName 参数必须与在应用主机项目中添加 PostgreSQL 服务器资源时使用的名称匹配。

前面的代码片段演示了如何使用AddAzureNpgsqlDbContext方法来注册一个YourDbContext实例,该实例使用身份验证(Azure)并具有(已共用以提高性能)的特点。 此 "postgresdb" 连接名称对应于连接字符串配置值。

YourDbContext 添加到生成器后,可以使用依赖项注入获取 YourDbContext 实例。 例如,若要从示例服务中检索数据源对象,请将其定义为构造函数参数,并确保 ExampleService 类注册到依赖项注入容器:

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

有关依赖项注入的详细信息,请参阅 .NET 依赖项注入

扩充 Npgsql 数据库上下文

你可能更喜欢使用标准 Entity Framework 方法获取数据库上下文并将其添加到依赖项注入容器:

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

注意

传递给 GetConnectionString 方法的连接字符串名称必须与在应用主机项目中添加 PostgreSQL 服务器资源时使用的名称匹配。 有关详细信息,请参阅 添加 PostgreSQL 服务器资源

以这种方式创建数据库上下文时具有更大的灵活性,例如:

  • 可以重复使用数据库上下文的现有配置代码,而无需为 .NET.NET Aspire重写它。
  • 可以使用 Entity Framework Core 拦截器来修改数据库操作。
  • 可以选择不使用 Entity Framework Core 上下文池,在某些情况下性能可能更好。

如果使用此方法,通过调用 .NET 方法,可以为数据库上下文添加 .NET AspireEnrichAzureNpgsqlDbContext 样式的重试、运行状况检查、日志记录和遥测功能。

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

settings 参数是 AzureNpgsqlEntityFrameworkCorePostgreSQLSettings 类的实例。

可能还需要配置 Npgsql 的特定选项,或者以其他方式注册 DbContext 。 在这种情况下,通过调用 EnrichAzureNpgsqlDbContext 扩展方法执行此作,如以下示例所示:

var connectionString = builder.Configuration.GetConnectionString("postgresdb");

builder.Services.AddDbContextPool<YourDbContext>(
    dbContextOptionsBuilder => dbContextOptionsBuilder.UseNpgsql(connectionString));

builder.EnrichAzureNpgsqlDbContext<YourDbContext>();

配置

.NET AspireAzurePostgreSQL EntityFrameworkCore Npgsql 集成提供了多个选项,用于根据项目的要求和约定配置数据库连接。

使用连接字符串

使用配置节中 ConnectionStrings 定义的连接字符串时,在调用 AddAzureNpgsqlDataSource时提供连接字符串的名称:

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

可以从 ConnectionStrings 配置部分中检索连接字符串。例如,考虑以下 JSON 配置:

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

有关如何配置连接字符串的详细信息,请参阅 Npgsql 连接字符串文档

注意

用户名和密码会自动从设置中提供的凭据推断。

使用配置提供器

.NET AspireAzurePostgreSQLEntityFrameworkCore Npgsql 集成支持 Microsoft.Extensions.Configuration。 它使用AzureNpgsqlEntityFrameworkCorePostgreSQLSettings密钥从配置中加载Aspire:Npgsql:EntityFrameworkCore:PostgreSQL。 例如,请考虑以下 appsettings.json 文件,该文件配置了一些可用选项:

{
  "Aspire": {
    "Npgsql": {
      "EntityFrameworkCore": {
        "PostgreSQL": {
          "DisableHealthChecks": true,
          "DisableTracing": true
        }
      }
    }
  }
}
使用内联委托

可以在代码中配置设置,通过传递 Action<AzureNpgsqlEntityFrameworkCorePostgreSQLSettings> configureSettings 委托来直接在代码中设置某些或所有选项,例如,从代码中禁用健康检查:

builder.AddAzureNpgsqlDbContext<YourDbContext>(
    "postgresdb",
    settings => settings.DisableHealthChecks = true);

或者,可以使用 EnrichAzureNpgsqlDbContext 扩展方法配置设置:

builder.EnrichAzureNpgsqlDbContext<YourDbContext>(
    settings => settings.DisableHealthChecks = true);

使用 AzureNpgsqlEntityFrameworkCorePostgreSQLSettings.Credential 属性建立连接。 如果未配置凭据,则使用 DefaultAzureCredential

当连接字符串包含用户名和密码时,将忽略凭据。

故障排除

在极少数情况下,如果未提供Username属性,并且集成无法使用应用程序的托管标识来检测它,Npgsql 会引发异常,其消息如下所示:

Npgsql.PostgresException (0x80004005): 28P01:用户密码身份验证失败...

在这种情况下,可以在连接字符串中配置 Username 属性并使用 EnrichAzureNpgsqlDbContext,通过 UseNpgsql 传递连接字符串。

builder.Services.AddDbContextPool<YourDbContext>(
    options => options.UseNpgsql(newConnectionString));

builder.EnrichAzureNpgsqlDbContext<YourDbContext>();

配置多个 DbContext 类

如果要注册多个具有不同配置的 DbContext,可以使用配置节名称为 $"Aspire:Npgsql:EntityFrameworkCore:PostgreSQL:{typeof(TContext).Name}"。 json 配置如下所示:

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

然后,使用 AddNpgsqlDbContext 类型参数调用 AnotherDbContext 方法将从 Aspire:Npgsql:EntityFrameworkCore:PostgreSQL:AnotherDbContext 节加载设置。

builder.AddAzureNpgsqlDbContext<AnotherDbContext>();

Client 整合健康检查

默认情况下,.NET.NET Aspire客户端集成 对所有服务启用了 健康检查。 同样,许多 .NET.NET Aspire托管集成 也启用健康检查端点。 有关详细信息,请参阅:

默认情况下,.NET AspirePostgreSQLEntity Framework Core 集成处理以下内容:

  • 添加了DbContextHealthCheck,它调用了EF Core的CanConnectAsync方法。 健康检查的名称是 TContext 类型的名称。
  • /health HTTP 终结点集成,该终结点指定所有已注册的运行状况检查都必须通过,才能使应用被视为已经准备好接受流量。

可观测性和遥测

.NET.NET Aspire 集成会自动设置日志记录、跟踪和指标配置,这些配置有时称为 可观测性的支柱。 有关集成可观测性和遥测的详细信息,请参阅 .NET.NET Aspire 集成概述。 根据支持服务,某些集成可能仅支持其中一些功能。 例如,某些集成支持日志记录和跟踪,但不支持指标。 也可以使用 配置 部分中介绍的技术禁用遥测功能。

伐木

.NET AspirePostgreSQLEntity Framework Core 集成使用以下日志类别:

  • 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

追踪

.NET AspirePostgreSQLEntity Framework Core 集成将使用 OpenTelemetry发出以下跟踪活动:

  • Npgsql

指标

.NET AspirePostgreSQLEntity Framework Core 集成将使用 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

另请参阅