# Connect to Azure PostgreSQL with EF Core

<Image
  src={postgresqlIcon}
  alt="Azure Database for PostgreSQL logo"
  width={100}
  height={100}
  class:list={'float-inline-left icon'}
  data-zoom-off
/>

This page describes how C# consuming apps connect to an Azure PostgreSQL resource that's already modeled in your AppHost using Entity Framework Core. For the AppHost API surface — adding an Azure PostgreSQL Flexible Server, databases, authentication, and more — see [Azure PostgreSQL Hosting integration](/integrations/cloud/azure/azure-postgresql/azure-postgresql-host/).

When you reference an Azure PostgreSQL resource from your AppHost, Aspire injects the connection information into the consuming app as environment variables. Your C# app can either read those environment variables directly or use the Aspire Azure PostgreSQL EF Core client integration for automatic dependency injection, health checks, and telemetry.

## Installation

To get started with the Aspire Azure PostgreSQL Entity Framework Core client integration, install the [📦 Aspire.Azure.Npgsql.EntityFrameworkCore.PostgreSQL](https://www.nuget.org/packages/Aspire.Azure.Npgsql.EntityFrameworkCore.PostgreSQL/) NuGet package in the client-consuming project, that is, the project for the application that uses the Azure PostgreSQL EF Core client. The Aspire Azure PostgreSQL Entity Framework Core client integration registers your desired `DbContext` subclass instances that you can use to interact with PostgreSQL.

<InstallDotNetPackage packageName="Aspire.Azure.Npgsql.EntityFrameworkCore.PostgreSQL" />

## Connection properties

Aspire exposes each property as an environment variable named `[RESOURCE]_[PROPERTY]`. For instance, the `Uri` property of a resource called `postgresdb` becomes `POSTGRESDB_URI`.

### Azure PostgreSQL Flexible Server resource

The Azure PostgreSQL Flexible Server resource exposes the following connection properties:

| Property Name          | Description |
| ---------------------- | ----------- |
| `Host`                 | The hostname or IP address of the Azure PostgreSQL Flexible Server |
| `Port`                 | The port number the PostgreSQL server is listening on |
| `Username`             | The username for authentication. Emitted when using password authentication; may be omitted when using Microsoft Entra ID authentication. |
| `Password`             | The password for authentication. Present only when using password authentication; not present when using Microsoft Entra ID authentication. |
| `Uri`                  | The connection URI in `postgresql://` format without embedded credentials, for example `postgresql://{Host}:{Port}?sslmode=Require` |
| `JdbcConnectionString` | JDBC-format connection string without embedded credentials, for example `jdbc:postgresql://{Host}:{Port}?sslmode=require&authenticationPluginClassName=com.azure.identity.extensions.jdbc.postgresql.AzurePostgresqlAuthenticationPlugin`. Credentials are provided as separate `Username` and `Password` properties when using password authentication. |

### Azure PostgreSQL database resource

The Azure PostgreSQL database resource inherits all properties from its parent `AzurePostgresFlexibleServerResource` and adds:

| Property Name          | Description |
| ---------------------- | ----------- |
| `Uri`                  | The connection URI in `postgresql://` format without embedded credentials, for example `postgresql://{Host}:{Port}/{DatabaseName}?sslmode=Require` |
| `JdbcConnectionString` | JDBC connection string including the database name without embedded credentials, for example `jdbc:postgresql://{Host}:{Port}/{DatabaseName}?sslmode=require&authenticationPluginClassName=com.azure.identity.extensions.jdbc.postgresql.AzurePostgresqlAuthenticationPlugin`. Credentials are provided as separate `Username` and `Password` properties when using password authentication. |
| `DatabaseName`         | The name of the database |

## Connect from your app

The recommended approach for C# apps is the Aspire Azure PostgreSQL EF Core client integration. It registers a pooled `DbContext` through dependency injection and adds health checks and telemetry automatically.

#### Install the client integration

Install the [📦 Aspire.Azure.Npgsql.EntityFrameworkCore.PostgreSQL](https://www.nuget.org/packages/Aspire.Azure.Npgsql.EntityFrameworkCore.PostgreSQL/) NuGet package in the client-consuming project:

<InstallDotNetPackage packageName="Aspire.Azure.Npgsql.EntityFrameworkCore.PostgreSQL" />

#### Add the DbContext

In _Program.cs_, call `AddAzureNpgsqlDbContext` on your `IHostApplicationBuilder` to register a pooled `DbContext` that uses Azure authentication ([Microsoft Entra ID](https://learn.microsoft.com/azure/postgresql/flexible-server/concepts-azure-ad-authentication)) by default:

```csharp title="C# — Program.cs"
builder.AddAzureNpgsqlDbContext<YourDbContext>(connectionName: "postgresdb");
```
**Note:** You must create a `DbContext` class called `YourDbContext` in your project. This class defines your database schema using EF Core. For more information on creating and configuring a `DbContext`, see [DbContext Lifetime, Configuration, and Initialization](https://learn.microsoft.com/ef/core/dbcontext-configuration/) in the EF Core documentation.
**Tip:** The `connectionName` must match the Azure PostgreSQL database resource name from the AppHost. For more information, see [Add an Azure Database for PostgreSQL resource](/integrations/cloud/azure/azure-postgresql/azure-postgresql-host/#add-an-azure-database-for-postgresql-resource).

Resolve the `DbContext` through dependency injection:

```csharp title="C# — ExampleService.cs"
public class ExampleService(YourDbContext context)
{
    // Use context...
}
```

For more information on dependency injection, see [.NET dependency injection](https://learn.microsoft.com/dotnet/core/extensions/dependency-injection).

#### Add keyed DbContext instances

To register multiple `DbContext` instances with different connection names, use the keyed service pattern by configuring separate named sections. See [Configure multiple DbContext classes](#configure-multiple-dbcontext-classes) for details.

#### Enrich a manually registered DbContext

If you need more control over `DbContext` registration — for example, to reuse existing configuration code, use EF Core interceptors, or opt out of context pooling — register the `DbContext` manually and call `EnrichAzureNpgsqlDbContext` to add Aspire health checks, retries, logging, and telemetry:

```csharp title="C# — Program.cs"
builder.Services.AddDbContext<YourDbContext>(options =>
    options.UseNpgsql(builder.Configuration.GetConnectionString("postgresdb")
        ?? throw new InvalidOperationException("Connection string 'postgresdb' not found.")));

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

The `settings` parameter is an instance of `AzureNpgsqlEntityFrameworkCorePostgreSQLSettings`.

#### Configuration

The client integration supports multiple ways to provide configuration.

**Connection strings.** When using a connection string from the `ConnectionStrings` configuration section, pass the connection name to `AddAzureNpgsqlDbContext`:

```csharp title="C# — Program.cs"
builder.AddAzureNpgsqlDbContext<YourDbContext>("postgresdb");
```

The connection string is resolved from the `ConnectionStrings` section:

```json title="JSON — appsettings.json"
{
  "ConnectionStrings": {
    "postgresdb": "Host=myserver;Database=test"
  }
}
```

The username and password are automatically inferred from the credential configured in the settings. For more information, see the [Npgsql connection string documentation](https://www.npgsql.org/doc/connection-string-parameters.html).

**Configuration providers.** The client integration supports `Microsoft.Extensions.Configuration`. It loads `AzureNpgsqlEntityFrameworkCorePostgreSQLSettings` from _appsettings.json_ using the `Aspire:Npgsql:EntityFrameworkCore:PostgreSQL` key:

```json title="JSON — appsettings.json"
{
  "Aspire": {
    "Npgsql": {
      "EntityFrameworkCore": {
        "PostgreSQL": {
          "DisableHealthChecks": true,
          "DisableTracing": true
        }
      }
    }
  }
}
```

**Inline delegates.** Pass an `Action<AzureNpgsqlEntityFrameworkCorePostgreSQLSettings>` to configure settings inline, for example to disable health checks:

```csharp title="C# — Program.cs"
builder.AddAzureNpgsqlDbContext<YourDbContext>(
    "postgresdb",
    settings => settings.DisableHealthChecks = true);
```

Use the `AzureNpgsqlEntityFrameworkCorePostgreSQLSettings.Credential` property to establish a connection. If no credential is configured, a [default Azure credential](/integrations/cloud/azure/azure-default-credential/) is used. When the connection string contains a username and password, the credential is ignored.

**Troubleshooting.** In the rare case that the `Username` property isn't provided and the integration can't detect it using the application's Managed Identity, Npgsql throws an exception similar to:

> Npgsql.PostgresException (0x80004005): 28P01: password authentication failed for user ...

In this case, configure the `Username` property in the connection string and use `EnrichAzureNpgsqlDbContext`:

```csharp title="C# — Program.cs"
builder.Services.AddDbContextPool<YourDbContext>(
    options => options.UseNpgsql(connectionString));

builder.EnrichAzureNpgsqlDbContext<YourDbContext>();
```

#### Configure multiple DbContext classes

To register more than one `DbContext` with different configuration, use the `$"Aspire:Npgsql:EntityFrameworkCore:PostgreSQL:{typeof(TContext).Name}"` configuration section name:

```json title="JSON — appsettings.json"
{
  "Aspire": {
    "Npgsql": {
      "EntityFrameworkCore": {
        "PostgreSQL": {
          "ConnectionString": "<YOUR CONNECTION STRING>",
          "DisableHealthChecks": true,
          "DisableTracing": true,
          "AnotherDbContext": {
            "ConnectionString": "<ANOTHER CONNECTION STRING>",
            "DisableTracing": false
          }
        }
      }
    }
  }
}
```

Call `AddAzureNpgsqlDbContext` with the `AnotherDbContext` type parameter to load settings from the `Aspire:Npgsql:EntityFrameworkCore:PostgreSQL:AnotherDbContext` section:

```csharp title="C# — Program.cs"
builder.AddAzureNpgsqlDbContext<AnotherDbContext>();
```

#### Client integration health checks

Aspire client integrations enable health checks by default. The Azure PostgreSQL EF Core client integration adds:

- The [`DbContextHealthCheck`](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/blob/master/src/HealthChecks.NpgSql/NpgSqlHealthCheck.cs), which calls EF Core's `CanConnectAsync` method. The name of the health check is the name of the `TContext` type.
- Integration with the `/health` HTTP endpoint, where all registered health checks must pass before the app is considered ready to accept traffic.

#### Observability and telemetry

The Aspire Azure PostgreSQL EF Core client integration automatically configures logging, tracing, and metrics through OpenTelemetry.

**Logging** categories:

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

**Tracing** activities:

- `Npgsql`

**Metrics**:

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

Any of these telemetry features can be disabled through the configuration options above.