Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions conceptual/EFCore.PG/release-notes/10.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,21 @@ For more information, [see the documentation](../modeling/generated-properties.m

By default, EF generates GUID (or UUID) values locally in .NET, rather than relying on the database to generate them. Version 9 of the PG provider already switched to generating UUIDv7 values by default ([see release note](9.0.md#uuidv7-guids-are-generated-by-default)), which are significantly better for database indexes. PostgreSQL 18 also added the [`uuidv7()`](https://www.postgresql.org/docs/18/functions-uuid.html#FUNC_UUID_GEN_TABLE) built-in function, which allows database generation of UUIDv7 values. In EFCore.PG 10, if you configure the provider to target PG 18 (`.UseNpgsql("...", o => o.SetPostgresVersion(18, 0))`), the provider will also translate [`Guid.CreateVersion7()`](https://learn.microsoft.com/dotnet/api/system.guid.createversion7) to that function.

## Support for the cube extension

PostgreSQL bundles the [`cube`](https://www.postgresql.org/docs/current/cube.html) extension, which provides a multi-dimensional cube data type and associated operations. EFCore.PG 10 now fully supports the `cube` type out-of-the-box, simply add an `NpgsqlCube` property to your entity type:

```c#
public class Blog
{
...

public NpgsqlCube Cube { get; set; }
}
```

Most translations over the type are supported as well. Thanks to [@kirkbrauer](https://github.com/kirkbrauer) for contributing this feature!

## Other new features

* NodaTime `LocalDate.At()` and `LocalDate.AtMidnight()` are now translated.
Expand Down
36 changes: 19 additions & 17 deletions conceptual/Npgsql/diagnostics/metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
Npgsql supports reporting aggregated metrics which provide snapshots on its state and activities at a given point. These can be especially useful for diagnostics issues such as connection leaks, or doing general performance analysis Metrics are reported via the standard .NET System.Diagnostics.Metrics API; [see these docs](https://learn.microsoft.com/dotnet/core/diagnostics/metrics) for more details. The Npgsql metrics implement the experimental [OpenTelemetry semantic conventions for database metrics](https://opentelemetry.io/docs/specs/semconv/database/database-metrics/) - adding some additional useful ones - and will evolve as that specification stabilizes.

> [!NOTE]
> Npgsql 10.0 changed the metrics names to align with the OpenTelemetry standard. The names shown below reflect the Npgsql 10 counters.
>
> Npgsql versions before 8.0, as well as TFMs under net6.0, emit metrics via the older Event Counters API instead of the new OpenTelemetry ones.

Metrics are usually collected and processed via tools such as [Prometheus](https://prometheus.io), and plotted on dashboards via tools such as [Grafana](https://grafana.com). Configuring .NET to emit metrics to these tools is beyond the scope of this documentation, but you can use the command-line tool `dotnet-counters` to quickly test Npgsql's support. To collect metrics via `dotnet-counters`, [install the `dotnet-counters` tool](https://docs.microsoft.com/dotnet/core/diagnostics/dotnet-counters). Then, find out your process PID, and run it as follows:
Expand All @@ -15,23 +17,23 @@ dotnet counters monitor Npgsql -p <PID>

```output
[Npgsql]
db.client.commands.bytes_read (By / 1 sec)
pool.name=CustomersDB 1,020
db.client.commands.bytes_written (By / 1 sec)
pool.name=CustomersDB 710
db.client.commands.duration (s)
pool.name=CustomersDB,Percentile=50 0.001
pool.name=CustomersDB,Percentile=95 0.001
pool.name=CustomersDB,Percentile=99 0.001
db.client.commands.executing ({command})
pool.name=CustomersDB 2
db.client.commands.prepared_ratio
pool.name=CustomersDB 0
db.client.connections.max ({connection})
pool.name=CustomersDB 100
db.client.connections.usage ({connection})
pool.name=CustomersDB,state=idle 3
pool.name=CustomersDB,state=used 2
db.client.operation.npgsql.bytes_read (By / 1 sec)
db.client.connection.pool.name=CustomersDB 1,020
db.client.operation.npgsql.bytes_written (By / 1 sec)
db.client.connection.pool.name=CustomersDB 710
db.client.operation.duration (s)
db.client.connection.pool.name=CustomersDB,Percentile=50 0.001
db.client.connection.pool.name=CustomersDB,Percentile=95 0.001
db.client.connection.pool.name=CustomersDB,Percentile=99 0.001
db.client.operation.npgsql.executing ({command})
db.client.connection.pool.name=CustomersDB 2
db.client.operation.npgsql.prepared_ratio
db.client.connection.pool.name=CustomersDB 0
db.client.connection.max ({connection})
db.client.connection.pool.name=CustomersDB 100
db.client.connection.count ({connection})
db.client.connection.pool.name=CustomersDB,state=idle 3
db.client.connection.pool.name=CustomersDB,state=used 2
```

Note that Npgsql emits multiple *dimensions* with the metrics, e.g. the connection states (idle or used). In addition, an identifier for the connection pool - or data source - is emitted with every metric, allowing you to separately track e.g. multiple databases accessed in the same applications. By default, the `pool.name` will be the connection string, but it can be useful to give your data sources a name for easier and more consistent tracking:
Expand Down
3 changes: 2 additions & 1 deletion conceptual/Npgsql/diagnostics/tracing.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ dataSourceBuilder.ConfigureTracing(o => o
This allows you to:

* Specify a filter which determines which commands get traced
* Set the the tracing span name (e.g. use the command's SQL as the span name)
* Set the tracing span name (e.g. use the command's SQL as the span name)
* Add arbitrary tags to the tracing span, based on the command
* Disable the time-to-first-read event that's emitted in spans
* Disable tracing physical connection open span

## Using `AsyncLocal` to pass arbitrary information to your callbacks

Expand Down
76 changes: 74 additions & 2 deletions conceptual/Npgsql/release-notes/10.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,80 @@
Npgsql version 10.0 is now in development, preview versions are available on [nuget.org](https://www.nuget.org/packages/Npgsql).

> [!NOTE]
> The 10.0 release notes will be published soon.
> We're considering to start dropping support for synchronous APIs (`NpgsqlConnection.Open`, `NpgsqlCommand.ExecuteNonQuery`, etc.) starting with Npgsql 11.0. The current plan is to deprecate the API by throwing a runtime exception by default (with a switch to re-enable synchronous I/O) for Npgsql 11.0, while possibly completely removing it for Npgsql 12.0. This is in line with ASP.NET Core and .NET APIs in general, which are moving in the direction of async I/O only (for example, `System.IO.Pipelines` doesn't have synchronous I/O). If you have any questions or want to share you experience/issues with async I/O, please feel free to post in the [issue](https://github.com/npgsql/npgsql/issues/5865).

While this is a relatively minor release in terms of changes, it does contain new features and improvements. Notable changes:

## GSSAPI session encryption

GSSAPI session encryption is an alternative to SSL/TLS session encryption, where special temporary tokens are used to encrypt traffic between the client and the server (MIT Kerberos is one of the GSSAPI providers that can be used for that), unlike SSL/TLS, where SSL certificate is used for the same purpose. You can use the `GssEncryptionMode` connection string parameter to control whether GSS session encryption is used; the default is `Prefer`, which will enable the feature if possible but proceed if it's not available. To learn more, see PostgreSQL [docs](https://www.postgresql.org/docs/current/gssapi-enc.html).

## Support for RequireAuth in connection string

`RequireAuth` is used to determine which authentication methods are allowed/required. For example, if you want to make sure that passwords aren't sent as cleartext or MD5, you can specify `RequireAuth=!Password,!MD5`. Or, if you want to make sure to always authenticate either via ScramSHA256 or GSS, then you can specify it as `RequireAuth=ScramSHA256,GSS`. To learn more, see PostgreSQL [docs](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNECT-REQUIRE-AUTH).

## Support for the cube extension

PostgreSQL bundles the [`cube`](https://www.postgresql.org/docs/current/cube.html) extension, which provides a multi-dimensional cube data type and associated operations. Npgsql 10 now fully supports the `cube` type out-of-the-box:

```c#
command.CommandText = """
CREATE EXTENSION IF NOT EXISTS cube;
CREATE TABLE data (my_cude CUBE);
""";
await command.ExecuteNonQueryAsync();

var cube = new NpgsqlCube([1.0, 2.0, 3.0], [4.0, 5.0, 6.0]);
command.CommandText = "INSERT INTO data (my_cude) VALUES ($1)";
command.Parameters.Add(new() { Value = cube });
await command.ExecuteNonQueryAsync();

command.CommandText = "SELECT my_cude FROM data";
var readCube = (NpgsqlCube)(await command.ExecuteScalarAsync())!;
Console.WriteLine($"Read cube: {readCube}");
```

Thanks to [@kirkbrauer](https://github.com/kirkbrauer) for contributing this feature!

## Various other changes

* OpenTelemetry tracing now also included by default for whenever a physical connection to database is open.
* Added support for `PGAPPNAME` environment variable. It's mapped to `ApplicationName` field of the connection string.
* Added support for SHA3 hash algorithms with SASL authentication. Previously, Npgsql falled back to SCRAM-SHA-256 if the certificate, provided by the database, had SHA3 signature algorithm.
* `NpgsqlConnection.Open` now wraps `SocketException` with `NpgsqlException` when hostname can't be resolved.
* Metrics names are now more aligned to the OpenTelemetry standard (see breaking change note below).
* The connection string now supports specifying `TargetSessionAttributes` when used with `NpgsqlDataSourceBuilder`. This means that code creating `NpgsqlDataSource` doesn't have to be aware that it's used with multiple hosts.

## Breaking changes

* The PostgreSQL `date` and `time` types are now read as .NET [`DateOnly`](https://learn.microsoft.com/dotnet/api/system.dateonly) and [`TimeOnly`](https://learn.microsoft.com/dotnet/api/system.timeonly), instead of [`DateTime`](https://learn.microsoft.com/dotnet/api/system.datetime) and [`TimeSpan`](https://learn.microsoft.com/dotnet/api/system.timespan), respectively. This affects non-generic read methods which return `object`, such as <xref:Npgsql.NpgsqlCommand.ExecuteScalarAsync*> and <xref:Npgsql.NpgsqlDataReader.GetValue*?displayProperty=nameWithType>; you can still read `DateTime` and `TimeSpan` via the generic <xref:Npgsql.NpgsqlDataReader.GetFieldValue%2A>.
### .NET 6 is no longer supported

With .NET 6 being out of support since November 2024, Npgsql 10.0 also drops support for .NET 6. This change allows us to have a much better capability parity between different versions of .NET, while also removing hundreds lines of compatibility-only code and simplifying the codebase.

### `date` and `time` are now mapped to `DateOnly` and `TimeOnly`

The PostgreSQL `date` and `time` types are now read as .NET [`DateOnly`](https://learn.microsoft.com/dotnet/api/system.dateonly) and [`TimeOnly`](https://learn.microsoft.com/dotnet/api/system.timeonly), instead of [`DateTime`](https://learn.microsoft.com/dotnet/api/system.datetime) and [`TimeSpan`](https://learn.microsoft.com/dotnet/api/system.timespan) by default, respectively. This affects non-generic read methods which return `object`, such as <xref:Npgsql.NpgsqlCommand.ExecuteScalarAsync*> and <xref:Npgsql.NpgsqlDataReader.GetValue*?displayProperty=nameWithType>; you can still read `DateTime` and `TimeSpan` via the generic <xref:Npgsql.NpgsqlDataReader.GetFieldValue%2A>.

### `cidr` is now mapped to `IPNetwork`

With .NET 6 no longer supported by Npgsql, the PostgreSQL `cidr` type is now mapped to `IPNetwork` by default instead of `NpgsqlCidr`. In addition, `NpgsqlCidr` is now obsolete and will be removed in the future.

### Metrics names have been changed to align with the OpenTelemetry standard

Npgsql emits metrics that provide various numeric information about commands and connections. Since these metrics were designed when the OpenTelemetry specifications were in an earlier stage, they did not align with current standard naming. Npgsql 10 changes metrics names to better align with the standard, allowing Npgsql metrics to be tracked in dashboards just like other standards-conforming database drivers. If you already have a dashboard set up to consume Npgsql metrics, its configuration will need to change to accomodate the new naming.

### Only root CA certificate is used to validate TLS chain

While establishing TLS connection with PostgreSQL, Npgsql will now only use the provided root CA certificate to validate TLS chain instead of using it in addition to the system CA store. This behaviour aligns with libpq and prevents establishing unintended connections.

### COPY operation's `Timeout` property now treats `Timeout.InfiniteTimeSpan` as an infinite timeout instead of `TimeSpan.Zero`

This is in line with other .NET API (like `NetworkStream.ReadTimeout`), where `Timeout.InfiniteTimeSpan` and `Timeout.Infinite` are treated as infinite.

### `PostgresException.BatchCommand` is `null` by default

This prevents accidental leak of queries and parameters when exceptions are logged. To change this behavior you can set `IncludeFailedBatchedCommand` in connection string to `true`.

### NpgsqlConnection.BeginText{Import,Export}Async now return NpgsqlCopyTextReader instead of TextWriter

The methods to start a text import/export operation have been changed to return a more specific `NpgsqlCopyTextReader`, rather than a general `TextWriter`; this was done since `NpgsqlCopyTextReader` exposes some additional APIs to allow cancelling and setting the timeout on a COPY operation. Since `NpgsqlCopyTextReader` extends `TextWriter`, this is a binary breaking change only - recompiling against the new version of Npgsql should work without any source changes.
6 changes: 6 additions & 0 deletions conceptual/Npgsql/types/basic.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ polygon | NpgsqlPolygon |
line | NpgsqlLine |
circle | NpgsqlCircle |
box | NpgsqlBox |
cube | NpgsqlCube<sup>5</sup> |
hstore | Dictionary<string, string> |
oid | uint |
xid | uint |
Expand All @@ -74,6 +75,8 @@ array types | Array (of element type) |

<sup>4</sup> Prior to version 8.0, the default mapping for `cidr` was `ValueTuple<IPAddress, int>`.

<sup>5</sup> Introduced in Npgsql 10.0.0. Requires the PostgreSQL [`cube`](https://www.postgresql.org/docs/current/cube.html) extension.

## Write mappings

There are three rules that determine the PostgreSQL type sent for a parameter:
Expand Down Expand Up @@ -122,6 +125,7 @@ polygon | NpgsqlPolygon |
line | NpgsqlLine | | Line |
circle | NpgsqlCircle | | Circle |
box | NpgsqlBox | | Box |
cube | NpgsqlCube<sup>4</sup> | | Cube |
hstore | IDictionary\<string, string\> | | Hstore |
oid | | uint | Oid |
xid | | uint | Xid |
Expand All @@ -140,6 +144,8 @@ array types | T[], List\<T\> |

<sup>3</sup>Types which can be read as `byte[]` can also be written as `ReadOnlyMemory<byte>` and `Stream`.

<sup>4</sup> Introduced in Npgsql 10.0.0. Requires the PostgreSQL [`cube`](https://www.postgresql.org/docs/current/cube.html) extension.

Notes when using Range and Array, bitwise-or NpgsqlDbType.Range or NpgsqlDbType.Array with the child type. For example, to construct the NpgsqlDbType for a `int4range`, write `NpgsqlDbType.Range | NpgsqlDbType.Integer`. To construct the NpgsqlDbType for an `int[]`, write `NpgsqlDbType.Array | NpgsqlDbType.Integer`.

For information about enums, [see the Enums and Composites page](enums_and_composites.md).