Skip to content

Commit

Permalink
Document PG12->14 default compat mode breaking change (#313)
Browse files Browse the repository at this point in the history
  • Loading branch information
roji authored Nov 13, 2023
1 parent 086efb7 commit 4978d68
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 16 deletions.
16 changes: 3 additions & 13 deletions conceptual/EFCore.PG/modeling/generated-properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,15 @@ The Npgsql EF Core provider allows you to choose which of the above you want on
* *Serial*: the traditional PostgreSQL serial column. This will create the column with the `serial` datatype. Recommended only if you are using an older PostgreSQL version.
* *Sequence HiLo*: See below

Prior to version 3.0, the Npgsql provider generates "serial" columns for ID columns; starting with version 3.0, it generates "identity by default" instead. In other words, when `ValueGeneratedOnAdd` is specified on a `short`, `int` or `long` property, the Npgsql provider will automatically map it to a serial or identity column. Note that EF Core will automatically recognize key properties by convention (e.g. a property called `Id` in your entity) and will implicitly set them to `ValueGeneratedOnAdd`; a standard model with ID columns should automatically get created with the appropriate column type.

> [!CAUTION]
> Since the default strategy has changed, if you have an existing database with migrations, the the first migration created after upgrading to version 3.0 will alter your tables and convert serial columns to identity ones. This is a sensitive, one-time migration operation that should be done with care, and carefully tested before deployment to production. Changing a value generation strategy is a significant change to an existing database.
The default value generation strategy is "identity by default". In other words, when EF decides that an int property should be value generated (e.g. because it's named `Id`, or because you explicitly specified `ValueGeneratedOnAdd` on it), the Npgsql provider will automatically map it to an identity column.

### Defining the default strategy for the entire model

You can easily control the value generation strategy for the entire model. For example, to opt out of the change to identity columns, simply place the following in your context's `OnModelCreating()`:

```c#
protected override void OnModelCreating(ModelBuilder modelBuilder)
=> modelBuilder.UseSerialColumns();
```

Note that if you are using PostgreSQL 9.6 or older, identity columns will not work. It is recommended to place the provider in compatibility mode with your specific version - this will also affect the default value generation strategy:

```c#
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseNpgsql("...", o => o.SetPostgresVersion(9, 6));
=> modelBuilder.UseIdentityByDefaultColumns();
```

### Defining the strategy for a single property
Expand Down Expand Up @@ -187,7 +177,7 @@ CREATE TRIGGER "UpdateTimestamp"
## Computed Columns

> [!NOTE]
> This feature works only on PostgreSQL 12 or above, and was introduced in version 3.0.0 of the provider.
> This feature works only on PostgreSQL 12 or above.
PostgreSQL 12 added support for [stored generated columns](https://www.postgresql.org/docs/current/ddl-generated-columns.html), and Npgsql feature supports that feature as well:

Expand Down
8 changes: 8 additions & 0 deletions conceptual/EFCore.PG/release-notes/8.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ Existing code using the above features will start throwing exceptions after upgr

Note that EF Core itself is not yet compatible with NativeAOT, and Npgsql can only be used in NativeAOT applications without EF Core.

### Default PostgreSQL compatibility mode has been bumped from 12 to 14

This means that the provider assumes at least PostgreSQL 14; if you're running against an older version, explicitly specify the PostgreSQL version when configuring your context:

```csharp
optionsBuilder.UseNpgsql("<connection string>", o => o.SetPostgresVersion(12, 0))
```

### Obsoleted HasPostgresArrayConversion

With EF 8.0 introducing first-class support for [primitive collections](https://devblogs.microsoft.com/dotnet/announcing-ef8-preview-4), the PostgreSQL driver aligned its PostgreSQL array support to use that. As a result, `HasPostgresArrayConversion` can no longer be used to configure value-converted arrays; instead, the new standard EF mechanism can be used.
Expand Down
6 changes: 3 additions & 3 deletions conceptual/Npgsql/basic-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,18 @@ For information on tweaking the pooling behavior (or turning it off), see the [p

### Connections without a data source

The data source concept is new in Npgsql 7.0, and is the recommended way to use Npgsql. When using older versions, connections where instantiated directly, rather than obtaining them from a data source:
The data source concept is new in Npgsql 7.0, and is the recommended way to use Npgsql. When using older versions, connections are instantiated directly, rather than obtaining them from a data source:

```csharp
await using var conn = new NpgsqlConnection(connectionString);
await conn.OpenAsync();
```

Direct instantiation of connection is still supported, but is discouraged for various reasons when using Npgsql 7.0.
Direct instantiation of connection is still supported, but is discouraged for various reasons when using Npgsql 7.0 or above.

## Other execution methods

Above, we executed SQL via [ExecuteReaderAsync](https://docs.microsoft.com/dotnet/api/system.data.common.dbcommand.executereaderasync). There are other ways to execute a command, based on what results you expect from it:
Above, we executed SQL via [ExecuteReaderAsync](https://docs.microsoft.com/dotnet/api/system.data.common.dbcommand.executereaderasync). There are various ways to execute a command, based on what results you expect from it:

1. [ExecuteNonQueryAsync](https://docs.microsoft.com/dotnet/api/system.data.common.dbcommand.executenonqueryasync): executes SQL which doesn't return any results, typically `INSERT`, `UPDATE` or `DELETE` statements. Returns the number of rows affected.
2. [ExecuteScalarAsync](https://docs.microsoft.com/dotnet/api/system.data.common.dbcommand.executescalarasync): executes SQL which returns a single, scalar value.
Expand Down

0 comments on commit 4978d68

Please sign in to comment.