Npgsql 9.0 Release Notes
Npgsql.EntityFrameworkCore.PostgreSQL version 9.0 is out and available on nuget.org.
Note
We're considering to start dropping support for synchronous APIs (NpgsqlConnection.Open
, NpgsqlCommand.ExecuteNonQuery
, etc.) starting with Npgsql 10.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 10.0, while possibly completely removing it for Npgsql 11.0. This is in line with ASP.NET Core and .NET runtime 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.
Tracing improvements
Several quality-of-life improvements have been implemented for Npgsql's OpenTelemetry tracing support. You can now do the following via the new NpgsqlDataSourceBuilder.ConfigureTracingOptions API:
- 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)
- Add arbitrary tags to the tracing span, based on the command
- Disable the time-to-first-read event that's emitted in spans
See the tracing documentation for more information.
Mapping improvements
Support System.Text.Json polymorphism with PostgreSQL jsonb
Note
If you're using EF Core, the below pertains to the EF provider's legacy POCO mapping, and not to the recommended ToJson mapping. Unfortunately, the latter does not yet support polymorphic serialization (support for this may be added in EF 10).
System.Text.Json has supported polymorphic serialization for a while, using a JSON $type
property as the type discriminator. However, it was required that the $type
property be at the top of the JSON document; this causes problems serializing to the PostgreSQL jsonb
type, since that type does not preserve property order in JSON objects.
System.Text.Json 9.0 brings support for out-of-order metadata reads, which is an opt-in feature allowing the $type
property to be anywhere in the JSON object. When using Npgsql, you can opt into this when configuring your NpgsqlDataSourceBuilder as follows:
var builder = new NpgsqlDataSourceBuilder("<connection string>");
builder
.EnableDynamicJson()
.ConfigureJsonOptions(new JsonSerializerOptions { AllowOutOfOrderMetadataProperties = true });
await using var dataSource = builder.Build();
Once that's done, you can use JSON polymorphism with jsonb
. If you're still targeting .NET 8.0, you can take a reference on System.Text.Json 9.0 in order to use AllowOutOfOrderMetadataProperties
.
Add support for cidr <-> IPNetwork mapping
.NET 8 added a new type IPNetwork which represents an IP network with an IPAddress containing the network prefix and an int
defining the prefix length. This type seems to be a perfect fit for PostgreSQL's cidr
type, which is why we added support to read and write it. The default when reading a cidr
is still NpgsqlCidr
in 9.0, though this will likely change in Npgsql 10.0. See this issue for more info.
Add support for interval's infinity values via NodaTime's Period.MinValue/Period.MaxValue
PostgreSQL 17 added support for infinity values with interval
type. In turn, Npgsql 9.0 adds native support to read and write them via NodaTime's Period.MinValue
and Period.MaxValue
. Note that while using this feature with previous versions of PostgreSQL, instead of infinity values you'll get the minimum and maximum values for interval
type due to the way infinity values are implemented by PostgreSQL. See this issue for more info.
Security-related improvements
- PostgreSQL 17 added support for direct SSL. Direct SSL allows clients to skip sending an SSL support request, which saves a roundtrip while opening a physical connection. This behavior is disabled by default (as it's not supported with previous versions of PostgreSQL), but you can enable it via the
SslNegotiation
property in connection string or environment variablePGSSLNEGOTIATION
. See this issue for more info. - The new NpgsqlDataSourceBuilder.UseSslClientAuthenticationOptionsCallback callback is called while connecting to PostgreSQL via
SslStream
, and allows users to modify SslClientAuthenticationOptions, e.g. to change the supported TLS ciphers. See this issue for more info. - The new NpgsqlDataSourceBuilder.UseNegotiateOptionsCallback callback is called while performing GSSAPI authentication (such as Kerberos), and allows users to modify NegotiateAuthenticationClientOptions, e.g. to change the
Credential
property to implement password-based Kerberos authentication. See this issue for more info.
Replication improvements
- Parallel in-progress transactions with logical streaming replication protocol V4 allow clients to handle multiple in-progress transactions in parallel instead of sequentially. See this issue for more info.
- ReplicationValue.GetFieldName()
ReplicationValue.GetFieldName
allows clients to receive the name of changed column while reading rows from replication stream. See this issue for more info.
Breaking changes
.NET Standard 2.0 (and .NET Framework) is not supported
Npgsql 9.0 drops support for .NET Standard 2.0, and in turn .NET Framework. Npgsql is a constantly evolving driver, which makes it problematic to add new features which use APIs that do not exist on older versions of .NET. This doesn't mean you can't use Npgsql with .NET Standard 2.0: we're still committed to supporting Npgsql 8.0 (which does support .NET Standard 2.0). See this issue for more info.
Change some PgOutputReplicationOptions properties to support logical streaming replication protocol V4
The main changes are in the PgOutputReplicationOptions
class, where ProtocolVersion
and StreamingMode
properties were changed to an enum. See this issue for more info.
Multiple ssl related callbacks on NpgsqlDataSourceBuilder are deprecated in favor of UseSslClientAuthenticationOptionsCallback
With the new UseSslClientAuthenticationOptionsCallback
callback, users have much more control over the way Npgsql connects to PostgreSQL via SslStream
. This makes other callbacks, like UseUserCertificateValidationCallback
and UseClientCertificate
less useful, which is why we're obsoleting them. See this issue for more info.
The default value of ConnectionLifetime property in connection string is set to 1 hour
Previously, the default value of this property was set to 0, which made connections last indefinitely. The old behavior was problematic because each physical connection on PostgreSQL's side holds on certain caches, which can only grow over time. See this pull request for more info.