diff --git a/conceptual/EF6.PG/index.md b/conceptual/EF6.PG/index.md index 910ba6a3..db786877 100644 --- a/conceptual/EF6.PG/index.md +++ b/conceptual/EF6.PG/index.md @@ -1,194 +1,194 @@ ---- -layout: doc -title: Entity Framework 6 ---- - -Npgsql has an Entity Framework 6 provider. You can use it by installing the -[EntityFramework6.Npgsql](https://www.nuget.org/packages/EntityFramework6.Npgsql/) nuget. - -## Basic Configuration ## - -Configuration for an Entity Framework application can be specified in a config file (app.config/web.config) or through code. The latter is known as code-based configuration. - -### Code-based ### - -To use Entity Framework with Npgsql, define a class that inherits from `DbConfiguration` in the same assembly as your class inheriting `DbContext`. Ensure that you configure provider services, a provider factory, a default connection factory as shown below: - -```csharp -using Npgsql; -using System.Data.Entity; - -class NpgSqlConfiguration : DbConfiguration -{ - public NpgSqlConfiguration() - { - var name = "Npgsql"; - - SetProviderFactory(providerInvariantName: name, - providerFactory: NpgsqlFactory.Instance); - - SetProviderServices(providerInvariantName: name, - provider: NpgsqlServices.Instance); - - SetDefaultConnectionFactory(connectionFactory: new NpgsqlConnectionFactory()); - } -} -``` - -### Config file ### - -When installing `EntityFramework6.Npgsql` nuget package, the relevant sections in `App.config` / `Web.config` are usually automatically updated. You typically only have to add your `connectionString` with the correct `providerName`. - -```xml - - - - - - - - - - - - - - - - - -``` - -## Guid Support ## - -Npgsql EF migrations support uses `uuid_generate_v4()` function to generate guids. -In order to have access to this function, you have to install the extension uuid-ossp through the following command: - -```sql -create extension "uuid-ossp"; -``` - -If you don't have this extension installed, when you run Npgsql migrations you will get the following error message: - -```text -ERROR: function uuid_generate_v4() does not exist -``` - -If the database is being created by Npgsql Migrations, you will need to -[run the `create extension` command in the `template1` database](http://stackoverflow.com/a/11584751). -This way, when the new database is created, the extension will be installed already. - -## Optimistic Concurrency ## - -EntityFramework supports [optimistic concurrency](https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/handling-concurrency-with-the-entity-framework-in-an-asp-net-mvc-application), through the [system column `xmin`](https://www.postgresql.org/docs/current/ddl-system-columns.html). To use this column as the concurrency token, some [customization is needed](https://github.com/npgsql/EntityFramework6.Npgsql/issues/8). The following code will setup `Department.Version` to map to `xmin`, while the `SqlGenerator` will generate `CREATE/ALTER TABLE` statements omitting system columns. - -```csharp -public class Department { - public string Version { get; private set; } -} - -[DbConfigurationType(typeof(Configuration))] -public class UniversityDbContext : DbContext -{ - public DbSet Departments { get; set; } - - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - modelBuilder.Entity() - .Property(p => p.Version) - .HasColumnName("xmin") - .HasColumnType("text") - .IsConcurrencyToken() - .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed); - base.OnModelCreating(modelBuilder); - } -} - -internal class Configuration : DbConfiguration -{ - public Configuration() - { - SetMigrationSqlGenerator("Npgsql", () => new SqlGenerator()); - } -} - -public class SqlGenerator : NpgsqlMigrationSqlGenerator -{ - private readonly string[] systemColumnNames = { "oid", "tableoid", "xmin", "cmin", "xmax", "cmax", "ctid" }; - - protected override void Convert(CreateTableOperation createTableOperation) - { - var systemColumns = createTableOperation.Columns.Where(x => systemColumnNames.Contains(x.Name)).ToArray(); - foreach (var systemColumn in systemColumns) - createTableOperation.Columns.Remove(systemColumn); - base.Convert(createTableOperation); - } -} -``` - -## Template Database ## - -When the Entity Framework 6 provider creates a database, it issues a simple `CREATE DATABASE` command. -In PostgreSQL, this implicitly uses `template1` as the template - anything existing in `template1` will -be copied to your new database. If you wish to change the database used as a template, you can specify -the `EF Template Database` connection string parameter. For more info see the -[PostgreSQL docs](https://www.postgresql.org/docs/current/static/sql-createdatabase.html). - -## Customizing DataReader Behavior ## - -You can use [an Entity Framework 6 IDbCommandInterceptor](https://msdn.microsoft.com/library/dn469464(v=vs.113).aspx) to wrap the `DataReader` instance returned by Npgsql when Entity Framework executes queries. This is possible using a ```DbConfiguration``` class. - -Example use cases: - -- Forcing all returned ```DateTime``` and ```DateTimeOffset``` values to be in the UTC timezone. -- Preventing accidental insertion of DateTime values having ```DateTimeKind.Unspecified```. -- Forcing all postgres date/time types to be returned to Entity Framework as ```DateTimeOffset```. - -```csharp -[DbConfigurationType(typeof(AppDbContextConfiguration))] -public class AppDbContext : DbContext -{ - // ... -} - -public class AppDbContextConfiguration : DbConfiguration -{ - public AppDbContextConfiguration() - { - this.AddInterceptor(new MyEntityFrameworkInterceptor()); - } -} - -class MyEntityFrameworkInterceptor : DbCommandInterceptor -{ - public override void ReaderExecuted( - DbCommand command, - DbCommandInterceptionContext interceptionContext) - { - if (interceptionContext.Result == null) return; - interceptionContext.Result = new WrappingDbDataReader(interceptionContext.Result); - } - - public override void ScalarExecuted( - DbCommand command, - DbCommandInterceptionContext interceptionContext) - { - interceptionContext.Result = ModifyReturnValues(interceptionContext.Result); - } - - static object ModifyReturnValues(object result) - { - // Transform and then - return result; - } -} - -class WrappingDbDataReader : DbDataReader, IDataReader -{ - // Wrap an existing DbDataReader, proxy all calls to the underlying instance, - // modify return values and/or parameters as needed... - public WrappingDbDataReader(DbDataReader reader) - { - } -} -``` +--- +layout: doc +title: Entity Framework 6 +--- + +Npgsql has an Entity Framework 6 provider. You can use it by installing the +[EntityFramework6.Npgsql](https://www.nuget.org/packages/EntityFramework6.Npgsql/) nuget. + +## Basic Configuration ## + +Configuration for an Entity Framework application can be specified in a config file (app.config/web.config) or through code. The latter is known as code-based configuration. + +### Code-based ### + +To use Entity Framework with Npgsql, define a class that inherits from `DbConfiguration` in the same assembly as your class inheriting `DbContext`. Ensure that you configure provider services, a provider factory, a default connection factory as shown below: + +```csharp +using Npgsql; +using System.Data.Entity; + +class NpgSqlConfiguration : DbConfiguration +{ + public NpgSqlConfiguration() + { + var name = "Npgsql"; + + SetProviderFactory(providerInvariantName: name, + providerFactory: NpgsqlFactory.Instance); + + SetProviderServices(providerInvariantName: name, + provider: NpgsqlServices.Instance); + + SetDefaultConnectionFactory(connectionFactory: new NpgsqlConnectionFactory()); + } +} +``` + +### Config file ### + +When installing `EntityFramework6.Npgsql` nuget package, the relevant sections in `App.config` / `Web.config` are usually automatically updated. You typically only have to add your `connectionString` with the correct `providerName`. + +```xml + + + + + + + + + + + + + + + + + +``` + +## Guid Support ## + +Npgsql EF migrations support uses `uuid_generate_v4()` function to generate guids. +In order to have access to this function, you have to install the extension uuid-ossp through the following command: + +```sql +create extension "uuid-ossp"; +``` + +If you don't have this extension installed, when you run Npgsql migrations you will get the following error message: + +```text +ERROR: function uuid_generate_v4() does not exist +``` + +If the database is being created by Npgsql Migrations, you will need to +[run the `create extension` command in the `template1` database](http://stackoverflow.com/a/11584751). +This way, when the new database is created, the extension will be installed already. + +## Optimistic Concurrency ## + +EntityFramework supports [optimistic concurrency](https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/handling-concurrency-with-the-entity-framework-in-an-asp-net-mvc-application), through the [system column `xmin`](https://www.postgresql.org/docs/current/ddl-system-columns.html). To use this column as the concurrency token, some [customization is needed](https://github.com/npgsql/EntityFramework6.Npgsql/issues/8). The following code will setup `Department.Version` to map to `xmin`, while the `SqlGenerator` will generate `CREATE/ALTER TABLE` statements omitting system columns. + +```csharp +public class Department { + public string Version { get; private set; } +} + +[DbConfigurationType(typeof(Configuration))] +public class UniversityDbContext : DbContext +{ + public DbSet Departments { get; set; } + + protected override void OnModelCreating(DbModelBuilder modelBuilder) + { + modelBuilder.Entity() + .Property(p => p.Version) + .HasColumnName("xmin") + .HasColumnType("text") + .IsConcurrencyToken() + .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed); + base.OnModelCreating(modelBuilder); + } +} + +internal class Configuration : DbConfiguration +{ + public Configuration() + { + SetMigrationSqlGenerator("Npgsql", () => new SqlGenerator()); + } +} + +public class SqlGenerator : NpgsqlMigrationSqlGenerator +{ + private readonly string[] systemColumnNames = { "oid", "tableoid", "xmin", "cmin", "xmax", "cmax", "ctid" }; + + protected override void Convert(CreateTableOperation createTableOperation) + { + var systemColumns = createTableOperation.Columns.Where(x => systemColumnNames.Contains(x.Name)).ToArray(); + foreach (var systemColumn in systemColumns) + createTableOperation.Columns.Remove(systemColumn); + base.Convert(createTableOperation); + } +} +``` + +## Template Database ## + +When the Entity Framework 6 provider creates a database, it issues a simple `CREATE DATABASE` command. +In PostgreSQL, this implicitly uses `template1` as the template - anything existing in `template1` will +be copied to your new database. If you wish to change the database used as a template, you can specify +the `EF Template Database` connection string parameter. For more info see the +[PostgreSQL docs](https://www.postgresql.org/docs/current/static/sql-createdatabase.html). + +## Customizing DataReader Behavior ## + +You can use [an Entity Framework 6 IDbCommandInterceptor](https://msdn.microsoft.com/library/dn469464(v=vs.113).aspx) to wrap the `DataReader` instance returned by Npgsql when Entity Framework executes queries. This is possible using a ```DbConfiguration``` class. + +Example use cases: + +- Forcing all returned ```DateTime``` and ```DateTimeOffset``` values to be in the UTC timezone. +- Preventing accidental insertion of DateTime values having ```DateTimeKind.Unspecified```. +- Forcing all postgres date/time types to be returned to Entity Framework as ```DateTimeOffset```. + +```csharp +[DbConfigurationType(typeof(AppDbContextConfiguration))] +public class AppDbContext : DbContext +{ + // ... +} + +public class AppDbContextConfiguration : DbConfiguration +{ + public AppDbContextConfiguration() + { + this.AddInterceptor(new MyEntityFrameworkInterceptor()); + } +} + +class MyEntityFrameworkInterceptor : DbCommandInterceptor +{ + public override void ReaderExecuted( + DbCommand command, + DbCommandInterceptionContext interceptionContext) + { + if (interceptionContext.Result == null) return; + interceptionContext.Result = new WrappingDbDataReader(interceptionContext.Result); + } + + public override void ScalarExecuted( + DbCommand command, + DbCommandInterceptionContext interceptionContext) + { + interceptionContext.Result = ModifyReturnValues(interceptionContext.Result); + } + + static object ModifyReturnValues(object result) + { + // Transform and then + return result; + } +} + +class WrappingDbDataReader : DbDataReader, IDataReader +{ + // Wrap an existing DbDataReader, proxy all calls to the underlying instance, + // modify return values and/or parameters as needed... + public WrappingDbDataReader(DbDataReader reader) + { + } +} +``` diff --git a/conceptual/EFCore.PG/mapping/general.md b/conceptual/EFCore.PG/mapping/general.md index 002d3e10..7734fe39 100644 --- a/conceptual/EFCore.PG/mapping/general.md +++ b/conceptual/EFCore.PG/mapping/general.md @@ -1,41 +1,41 @@ -# Type mapping - -The EF Core provider transparently maps the types supported by Npgsql at the ADO.NET level - see [the Npgsql ADO type mapping page](/doc/types/basic.html). - -This means that you can use PostgreSQL-specific types, such as `inet` or `circle`, directly in your entities. Simply define your properties just as if they were a simple type, such as a `string`: - -```csharp -public class MyEntity -{ - public int Id { get; set; } - public string Name { get; set; } - public IPAddress IPAddress { get; set; } - public NpgsqlCircle Circle { get; set; } - public int[] SomeInts { get; set; } -} -``` - -Special types such as [arrays](array.md) and [enums](enum.md) have their own documentation pages with more details. - -[PostgreSQL composite types](https://www.postgresql.org/docs/current/static/rowtypes.html), while supported at the ADO.NET level, aren't yet supported in the EF Core provider. This is tracked by [#22](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/22). - -## Explicitly specifying data types - -In some cases, your .NET property type can be mapped to several PostgreSQL data types; a good example is a `string`, which will be mapped to `text` by default, but can also be mapped to `jsonb`. You can use either Data Annotation attributes or the Fluent API to configure the PostgreSQL data type: - -## [Data Annotations](#tab/data-annotations) - -```csharp -[Column(TypeName="jsonb")] -public string SomeStringProperty { get; set; } -``` - -## [Fluent API](#tab/fluent-api) - -```csharp -builder.Entity() - .Property(b => b.SomeStringProperty) - .HasColumnType("jsonb"); -``` - -*** +# Type mapping + +The EF Core provider transparently maps the types supported by Npgsql at the ADO.NET level - see [the Npgsql ADO type mapping page](/doc/types/basic.html). + +This means that you can use PostgreSQL-specific types, such as `inet` or `circle`, directly in your entities. Simply define your properties just as if they were a simple type, such as a `string`: + +```csharp +public class MyEntity +{ + public int Id { get; set; } + public string Name { get; set; } + public IPAddress IPAddress { get; set; } + public NpgsqlCircle Circle { get; set; } + public int[] SomeInts { get; set; } +} +``` + +Special types such as [arrays](array.md) and [enums](enum.md) have their own documentation pages with more details. + +[PostgreSQL composite types](https://www.postgresql.org/docs/current/static/rowtypes.html), while supported at the ADO.NET level, aren't yet supported in the EF Core provider. This is tracked by [#22](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/22). + +## Explicitly specifying data types + +In some cases, your .NET property type can be mapped to several PostgreSQL data types; a good example is a `string`, which will be mapped to `text` by default, but can also be mapped to `jsonb`. You can use either Data Annotation attributes or the Fluent API to configure the PostgreSQL data type: + +## [Data Annotations](#tab/data-annotations) + +```csharp +[Column(TypeName="jsonb")] +public string SomeStringProperty { get; set; } +``` + +## [Fluent API](#tab/fluent-api) + +```csharp +builder.Entity() + .Property(b => b.SomeStringProperty) + .HasColumnType("jsonb"); +``` + +*** diff --git a/conceptual/EFCore.PG/mapping/translations.md b/conceptual/EFCore.PG/mapping/translations.md index 5e8d4d90..b5cfcf64 100644 --- a/conceptual/EFCore.PG/mapping/translations.md +++ b/conceptual/EFCore.PG/mapping/translations.md @@ -1,6 +1,6 @@ # Translations -Entity Framework Core allows providers to translate query expressions to SQL for database evaluation. For example, PostgreSQL supports [regular expression operations](http://www.postgresql.org/docs/current/static/functions-matching.html#FUNCTIONS-POSIX-REGEXP), and the Npgsql EF Core provider automatically translates .NET's [`Regex.IsMatch`](https://docs.microsoft.com/dotnet/api/system.text.regularexpressions.regex.ismatch) to use this feature. Since evaluation happens at the server, table data doesn't need to be transferred to the client (saving bandwidth), and in some cases indexes can be used to speed things up. The same csharp code on other providers will trigger client evaluation. +Entity Framework Core allows providers to translate query expressions to SQL for database evaluation. For example, PostgreSQL supports [regular expression operations](http://www.postgresql.org/docs/current/static/functions-matching.html#FUNCTIONS-POSIX-REGEXP), and the Npgsql EF Core provider automatically translates .NET's [`Regex.IsMatch`](https://docs.microsoft.com/dotnet/api/system.text.regularexpressions.regex.ismatch) to use this feature. Since evaluation happens at the server, table data doesn't need to be transferred to the client (saving bandwidth), and in some cases indexes can be used to speed things up. The same C# code on other providers will trigger client evaluation. The Npgsql-specific translations are listed below. Some areas, such as [full-text search](full-text-search.md), have their own pages in this section which list additional translations. diff --git a/conceptual/EFCore.PG/release-notes/2.1.md b/conceptual/EFCore.PG/release-notes/2.1.md index e8d198ad..4362191a 100644 --- a/conceptual/EFCore.PG/release-notes/2.1.md +++ b/conceptual/EFCore.PG/release-notes/2.1.md @@ -1,119 +1,119 @@ -# 2.1 Release Notes - -Version 2.1.0 of the Npgsql Entity Framework Core provider has been released and is available on nuget. This version works with [version 2.1.0 of Entity Framework Core](https://docs.microsoft.com/ef/core/what-is-new/ef-core-2.1), and contains some new Npgsql features as well. - -Thanks to [@rwasef1830](https://github.com/rwasef1830) and [@austindrenski](https://github.com/austindrenski) for their valuable contributions. - -## New Features - -Aside from general EF Core features new in 2.1.0, the Npgsql provider contains the following major new features: - -### Improved Spatial Support (PostGIS) - -Previous versions have allowed basic usage of PostGIS's spatial types via built-in Npgsql types such as `NpgsqlPoint`, `NpgsqlLineString`, etc. These types were limited in many ways, and no operation translation was supported. If you want to calculate, say, the distance between two points, you had to drop down to raw SQL. - -No more! Thanks to a new plugin infrastructure, the EF Core provider now has full-class support for PostGIS. You can now use the [NetTopologySuite](https://github.com/NetTopologySuite/NetTopologySuite) spatial library to map PostGIS types - NetTopologySuite's types are more complete, and best of all, the provider knows how to translate its operations to SQL. This allows you to write the following code: - -```csharp -var nearbyCities = context.Cities.Where(c => c.Location.Distance(somePoint) < 100); -``` - -See [the full documentation for more information](../mapping/nts.md). - -Thanks to [@YohDeadfall](https://github.com/YohDeadfall) for implementing support for this at the ADO level. - -### Full text search - -PostgreSQL has a powerful feature for efficient natural-language search across multiple columns and tables, [see the PostgreSQL docs for more info](https://www.postgresql.org/docs/current/static/textsearch.html). The EF Core provider now supports full-text search, allowing you to use .NET functions in your LINQ queries which will get translated to efficient PostgreSQL natural-language search queries. - -Read [the full documentation for more information](../mapping/full-text-search.md). - -Many thanks to [@rwasef1830](https://github.com/rwasef1830) for contributing this feature. - -### NodaTime date/time support - -[NodaTime](https://nodatime.org) is a powerful alternative to .NET's built-in date/time types, such as `DateTime`. The built-in types are flawed in many ways: they have problematic support for timezones, don't have a date-only or time-only types, and promote problematic programming but not making the right distinctions. If your application handles dates and times in anything but the most basic way, you should seriously consider using NodaTime. To learn more read [this blog post by Jon Skeet](https://blog.nodatime.org/2011/08/what-wrong-with-datetime-anyway.html). - -Thanks to a new plugin infrastructure, it is now possible to set up the EF Core provider to use NodaTime's types instead of the built-in .NET ones; instead of having `DateTime` properties on your entities, you can now have [Instant](https://nodatime.org/2.2.x/userguide/core-types) properties instead. - -See [the full documentation for more information](../mapping/nodatime.md). - -### PostgreSQL 10 IDENTITY columns - -PostgreSQL 10 introduced a new IDENTITY column as an alternative to traditional SERIAL columns, and these are now supported by the EF Core provider. IDENTITY columns conform to the SQL standard and are in general safer than SERIAL columns, [read this blog post for more info](https://docs.microsoft.com/ef/core/what-is-new/ef-core-2.1). It's recommended that all new projects use IDENTITY, but Npgsql even provides seamless migration of your existing SERIAL-based model!. - -Read [the full documentation for more information](../modeling/generated-properties.md). - -### Enum support - -It is now possible to map your CLR enums to [native PostgreSQL enums](https://www.postgresql.org/docs/current/static/datatype-enum.html). This is a unique PostgreSQL feature that provides the best of both worlds: the enum is internally stored in the database as a number (minimal storage), but is handled like a string (more usable, no need to remember numeric values) and has type safety. - -See [the full documentation for more information](../mapping/enum.md). - -### Range support - -PostgreSQL supports [native range types](https://www.postgresql.org/docs/current/static/rangetypes.html), which allow you to represent ranges of dates, ints and other data types in a single column. You can then efficiently perform queries on these types from LINQ, e.g. select all rows where a given date falls in the row's date range. - -See [the full documentation for more information](../mapping/range.md). - -Many thanks to [@austindrenski](https://github.com/austindrenski) for contributing the operation translations. - -### Other notable features - -* Several improvements have been made to the way arrays are mapped. For example, you can now map `List` to PostgreSQL array (previously only `T[]` was supported) ([#392](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/392)). In addition, change tracking now works for arrays, so EF Core will automatically detect when you change an element's array and will update the corresponding database column when saving. -* PostgreSQL's built-in range types can now be mapped ([#63](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/63)), head over to the [PostgreSQL docs](https://www.postgresql.org/docs/current/static/rangetypes.html) to find out more about range types. Note that user-defined range types are *not* supported, if you're interested let us know at [#329](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/329). -* Properties of type `char` are now supported and will be mapped to `character(1)` in PostgreSQL ([#374](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/374)). -* Identifiers in generated SQL will only be quoted if needed ([#327](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/327)). This should make it much easier to read. -* You can now use client certificate authentication and provide a server certificate validation callback ([#270](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/270)). See [the doc for usage instructions](http://www.npgsql.org/efcore/misc.html#certificate-authentication). -* Added support for PostgreSQL 10 sequences with type `int` and `smallint` ([#301](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/301)). -* You can now specify the [tablespace](https://www.postgresql.org/docs/current/static/manage-ag-tablespaces.html) when creating your databases ([#332](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/332)). - -Here's the [full list of issues](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/milestone/8?closed=1). Please report any problems on . - -## Breaking changes - -> [!CAUTION] -> The provider's classes have been moved from the namespace `Microsoft.EntityFrameworkCore` to `Npgsql.EntityFrameworkCore.PostgreSQL`. As a result, any migrations already generated in your project (as well as the mode snapshot) will have to be manually updated to use the new namespace. You will need to add `using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata` to all the relevant files. - -* Columns of type `timestamp with time zone`/`timestamptz` will now be scaffolded as `DateTime` properties, and not `DateTimeOffset` properties. The general use of `timestamp with time zone`/`timestamptz` is discouraged (this type does *not* store the timezone in the database), consider using `timestamp without time zone`/`timestamp` instead. -* If you're specifying index methods with `ForNpgsqlHasMethod()`, then you will have to fix migrations which generate those indexes. In these migrations, you will find code such as `.Annotation("Npgsql:Npgsql:IndexMethod", "gin")`. You must remove the extra `Npgsql:`, leaving `.Annotation("Npgsql:IndexMethod", "gin")`. -* Specifying versions when specifying PostgreSQL extensions on your model is no longer supported - this was a very rarely-used feature which interfered with extension scaffolding. -* If you're still referencing the nuget package Npgsql.EntityFrameworkCore.PostgreSQL.Design, please remove it - it's no longer needed or up to date. - -## Contributors - -Thank you very much to the following people who have contributed to the individual 2.1.x. releases. - -### [Milestone 2.1.2](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.2) - -Contributor | Assigned issues ----------------------------------------------------- | ----------------:| -[@roji](https://github.com/roji) | [6](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.2+is%3Aclosed+assignee%3Aroji) -[@austindrenski](https://github.com/austindrenski) | [3](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.2+is%3Aclosed+assignee%3Aaustindrenski) -[@rwasef1830](https://github.com/rwasef1830) | [1](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.2+is%3Aclosed+assignee%3Arwasef1830) - -### [Milestone 2.1.11](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.11) - -Contributor | Assigned issues ----------------------------------------------------- | ----------------:| -[@roji](https://github.com/roji) | [1](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.11+is%3Aclosed+assignee%3Aroji) - -### [Milestone 2.1.1.1](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.1.1) - -Contributor | Assigned issues ----------------------------------------------------- | ----------------:| -[@roji](https://github.com/roji) | [4](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.1.1+is%3Aclosed+assignee%3Aroji) - -### [Milestone 2.1.1](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.1) - -Contributor | Assigned issues ----------------------------------------------------- | ----------------:| -[@roji](https://github.com/roji) | [9](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.1+is%3Aclosed+assignee%3Aroji) - -### [Milestone 2.1.0](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.0) - -| Contributor | Assigned issues -| -------------------------------------------------- | ----------------:| -| [@roji](https://github.com/roji) | [24](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.0+is%3Aclosed+assignee%3Aroji) -| [@austindrenski](https://github.com/austindrenski) | [1](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.0+is%3Aclosed+assignee%3Aaustindrenski) -| [@rwasef1830](https://github.com/rwasef1830) | [1](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.0+is%3Aclosed+assignee%3Arwasef1830) +# 2.1 Release Notes + +Version 2.1.0 of the Npgsql Entity Framework Core provider has been released and is available on nuget. This version works with [version 2.1.0 of Entity Framework Core](https://docs.microsoft.com/ef/core/what-is-new/ef-core-2.1), and contains some new Npgsql features as well. + +Thanks to [@rwasef1830](https://github.com/rwasef1830) and [@austindrenski](https://github.com/austindrenski) for their valuable contributions. + +## New Features + +Aside from general EF Core features new in 2.1.0, the Npgsql provider contains the following major new features: + +### Improved Spatial Support (PostGIS) + +Previous versions have allowed basic usage of PostGIS's spatial types via built-in Npgsql types such as `NpgsqlPoint`, `NpgsqlLineString`, etc. These types were limited in many ways, and no operation translation was supported. If you want to calculate, say, the distance between two points, you had to drop down to raw SQL. + +No more! Thanks to a new plugin infrastructure, the EF Core provider now has full-class support for PostGIS. You can now use the [NetTopologySuite](https://github.com/NetTopologySuite/NetTopologySuite) spatial library to map PostGIS types - NetTopologySuite's types are more complete, and best of all, the provider knows how to translate its operations to SQL. This allows you to write the following code: + +```csharp +var nearbyCities = context.Cities.Where(c => c.Location.Distance(somePoint) < 100); +``` + +See [the full documentation for more information](../mapping/nts.md). + +Thanks to [@YohDeadfall](https://github.com/YohDeadfall) for implementing support for this at the ADO level. + +### Full text search + +PostgreSQL has a powerful feature for efficient natural-language search across multiple columns and tables, [see the PostgreSQL docs for more info](https://www.postgresql.org/docs/current/static/textsearch.html). The EF Core provider now supports full-text search, allowing you to use .NET functions in your LINQ queries which will get translated to efficient PostgreSQL natural-language search queries. + +Read [the full documentation for more information](../mapping/full-text-search.md). + +Many thanks to [@rwasef1830](https://github.com/rwasef1830) for contributing this feature. + +### NodaTime date/time support + +[NodaTime](https://nodatime.org) is a powerful alternative to .NET's built-in date/time types, such as `DateTime`. The built-in types are flawed in many ways: they have problematic support for timezones, don't have a date-only or time-only types, and promote problematic programming but not making the right distinctions. If your application handles dates and times in anything but the most basic way, you should seriously consider using NodaTime. To learn more read [this blog post by Jon Skeet](https://blog.nodatime.org/2011/08/what-wrong-with-datetime-anyway.html). + +Thanks to a new plugin infrastructure, it is now possible to set up the EF Core provider to use NodaTime's types instead of the built-in .NET ones; instead of having `DateTime` properties on your entities, you can now have [Instant](https://nodatime.org/2.2.x/userguide/core-types) properties instead. + +See [the full documentation for more information](../mapping/nodatime.md). + +### PostgreSQL 10 IDENTITY columns + +PostgreSQL 10 introduced a new IDENTITY column as an alternative to traditional SERIAL columns, and these are now supported by the EF Core provider. IDENTITY columns conform to the SQL standard and are in general safer than SERIAL columns, [read this blog post for more info](https://docs.microsoft.com/ef/core/what-is-new/ef-core-2.1). It's recommended that all new projects use IDENTITY, but Npgsql even provides seamless migration of your existing SERIAL-based model!. + +Read [the full documentation for more information](../modeling/generated-properties.md). + +### Enum support + +It is now possible to map your CLR enums to [native PostgreSQL enums](https://www.postgresql.org/docs/current/static/datatype-enum.html). This is a unique PostgreSQL feature that provides the best of both worlds: the enum is internally stored in the database as a number (minimal storage), but is handled like a string (more usable, no need to remember numeric values) and has type safety. + +See [the full documentation for more information](../mapping/enum.md). + +### Range support + +PostgreSQL supports [native range types](https://www.postgresql.org/docs/current/static/rangetypes.html), which allow you to represent ranges of dates, ints and other data types in a single column. You can then efficiently perform queries on these types from LINQ, e.g. select all rows where a given date falls in the row's date range. + +See [the full documentation for more information](../mapping/range.md). + +Many thanks to [@austindrenski](https://github.com/austindrenski) for contributing the operation translations. + +### Other notable features + +* Several improvements have been made to the way arrays are mapped. For example, you can now map `List` to PostgreSQL array (previously only `T[]` was supported) ([#392](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/392)). In addition, change tracking now works for arrays, so EF Core will automatically detect when you change an element's array and will update the corresponding database column when saving. +* PostgreSQL's built-in range types can now be mapped ([#63](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/63)), head over to the [PostgreSQL docs](https://www.postgresql.org/docs/current/static/rangetypes.html) to find out more about range types. Note that user-defined range types are *not* supported, if you're interested let us know at [#329](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/329). +* Properties of type `char` are now supported and will be mapped to `character(1)` in PostgreSQL ([#374](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/374)). +* Identifiers in generated SQL will only be quoted if needed ([#327](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/327)). This should make it much easier to read. +* You can now use client certificate authentication and provide a server certificate validation callback ([#270](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/270)). See [the doc for usage instructions](http://www.npgsql.org/efcore/misc.html#certificate-authentication). +* Added support for PostgreSQL 10 sequences with type `int` and `smallint` ([#301](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/301)). +* You can now specify the [tablespace](https://www.postgresql.org/docs/current/static/manage-ag-tablespaces.html) when creating your databases ([#332](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/332)). + +Here's the [full list of issues](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/milestone/8?closed=1). Please report any problems on . + +## Breaking changes + +> [!CAUTION] +> The provider's classes have been moved from the namespace `Microsoft.EntityFrameworkCore` to `Npgsql.EntityFrameworkCore.PostgreSQL`. As a result, any migrations already generated in your project (as well as the mode snapshot) will have to be manually updated to use the new namespace. You will need to add `using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata` to all the relevant files. + +* Columns of type `timestamp with time zone`/`timestamptz` will now be scaffolded as `DateTime` properties, and not `DateTimeOffset` properties. The general use of `timestamp with time zone`/`timestamptz` is discouraged (this type does *not* store the timezone in the database), consider using `timestamp without time zone`/`timestamp` instead. +* If you're specifying index methods with `ForNpgsqlHasMethod()`, then you will have to fix migrations which generate those indexes. In these migrations, you will find code such as `.Annotation("Npgsql:Npgsql:IndexMethod", "gin")`. You must remove the extra `Npgsql:`, leaving `.Annotation("Npgsql:IndexMethod", "gin")`. +* Specifying versions when specifying PostgreSQL extensions on your model is no longer supported - this was a very rarely-used feature which interfered with extension scaffolding. +* If you're still referencing the nuget package Npgsql.EntityFrameworkCore.PostgreSQL.Design, please remove it - it's no longer needed or up to date. + +## Contributors + +Thank you very much to the following people who have contributed to the individual 2.1.x. releases. + +### [Milestone 2.1.2](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.2) + +Contributor | Assigned issues +---------------------------------------------------- | ----------------:| +[@roji](https://github.com/roji) | [6](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.2+is%3Aclosed+assignee%3Aroji) +[@austindrenski](https://github.com/austindrenski) | [3](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.2+is%3Aclosed+assignee%3Aaustindrenski) +[@rwasef1830](https://github.com/rwasef1830) | [1](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.2+is%3Aclosed+assignee%3Arwasef1830) + +### [Milestone 2.1.11](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.11) + +Contributor | Assigned issues +---------------------------------------------------- | ----------------:| +[@roji](https://github.com/roji) | [1](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.11+is%3Aclosed+assignee%3Aroji) + +### [Milestone 2.1.1.1](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.1.1) + +Contributor | Assigned issues +---------------------------------------------------- | ----------------:| +[@roji](https://github.com/roji) | [4](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.1.1+is%3Aclosed+assignee%3Aroji) + +### [Milestone 2.1.1](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.1) + +Contributor | Assigned issues +---------------------------------------------------- | ----------------:| +[@roji](https://github.com/roji) | [9](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.1+is%3Aclosed+assignee%3Aroji) + +### [Milestone 2.1.0](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.0) + +| Contributor | Assigned issues +| -------------------------------------------------- | ----------------:| +| [@roji](https://github.com/roji) | [24](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.0+is%3Aclosed+assignee%3Aroji) +| [@austindrenski](https://github.com/austindrenski) | [1](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.0+is%3Aclosed+assignee%3Aaustindrenski) +| [@rwasef1830](https://github.com/rwasef1830) | [1](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.1.0+is%3Aclosed+assignee%3Arwasef1830) diff --git a/conceptual/EFCore.PG/release-notes/2.2.md b/conceptual/EFCore.PG/release-notes/2.2.md index 0249af47..89de0f84 100644 --- a/conceptual/EFCore.PG/release-notes/2.2.md +++ b/conceptual/EFCore.PG/release-notes/2.2.md @@ -1,81 +1,81 @@ -# 2.2 Release Notes - -Version 2.2.0 of the Npgsql Entity Framework Core provider has been released and is available on nuget. This version works with [version 2.2.0 of Entity Framework Core](https://docs.microsoft.com/ef/core/what-is-new/ef-core-2.2), and contains some new Npgsql features as well. - -This release was result of hard work by [@roji](https://github.com/roji/), [@austindrenski](https://github.com/austindrenski), [@yohdeadfall](https://github.com/yohdeadfall) and [@khellang](https://github.com/khellang). - -## New Features - -Aside from general EF Core features new in 2.2.0, the Npgsql EF Core provider contains the following major new features: - -### PostgreSQL 11 covering indexes - -PostgreSQL 11 introduced [covering indexes feature](https://paquier.xyz/postgresql-2/postgres-11-covering-indexes), which allow you to include "non-key" columns in your indexes. This allows you to perform index-only scans and can provide a significant performance boost. Support has been added in ([#697](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/697)): - -```csharp -protected override void OnConfiguring(DbContextOptionsBuilder builder) - => modelBuilder.Entity() - .ForNpgsqlHasIndex(b => b.Id) - .ForNpgsqlInclude(b => b.Name); -``` - -This will create an index for searching on `Id`, but containing also the column `Name`, so that reading the latter will not involve accessing the table. [See the documentation for more details](../modeling/indexes.md). - -Thanks to [@khellang](https://github.com/khellang) for contributing this! - -### PostgreSQL user-defined ranges - -The provider already supported [PostgreSQL range types](https://www.postgresql.org/docs/current/rangetypes.html), but prior to 2.2 that support was limited to the built-in range types which come with PostgreSQL. [#329](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/329) extends that support to range types which you define: - -```csharp -protected override void OnConfiguring(DbContextOptionsBuilder builder) - => builder.UseNpgsql("...", b => b.MapRange("floatrange")); - -protected override void OnModelCreating(ModelBuilder builder) - => builder.ForNpgsqlHasRange("floatrange", "real"); -``` - -This will make the provider create a PostgreSQL range called `floatrange`, over the PostgreSQL type `real`. Any property with type `NpgsqlRange` will be seamlessly mapped to it. - -[See the documentation for more details](../mapping/range.md). - -### Seeding for Npgsql-specific types - -When using some Npgsql-specific types, it wasn't possible to seed values for those types. With EF Core support for seeding any type, [#667](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/667) allows seeding values for network, bit and range types (more are coming). - -### PostgreSQL index operator classes - -PostgreSQL allows you to specify [operator classes on your indexes](https://www.postgresql.org/docs/current/indexes-opclass.html), to allow tweaking how the index should work. [#481](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/481) adds support for managing these. [See the documentation for more details](../modeling/indexes.md). - -Thanks to [@khellang](https://github.com/khellang) for contributing this! - -### Other features - -* Various issues with enum and range types were fixed, including upper/lower case, quoting and schema management. -* Many new SQL translations were added, so more of your LINQ expressions can run in the database. We'll be working on our documentation to make these more discoverable. - -The full list of issues for this release is [available here](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues?q=milestone%3A2.2.0+is%3Aclosed&utf8=%E2%9C%93). - -## Contributors - -Thank you very much to the following people who have contributed to the individual 2.2.x. releases. - -### [Milestone 2.2.6](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.2.6) - -Contributor | Assigned issues ------------------------------------------------- | ----------------:| -[@roji](https://github.com/roji) |[5](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.2.6+is%3Aclosed+assignee%3Aroji) - -### [Milestone 2.2.4](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.2.4) - -Contributor | Assigned issues --------------------------------------------------- | ----------------:| -[@roji](https://github.com/roji) | [3](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.2.4+is%3Aclosed+assignee%3Aroji) -[@austindrenski](https://github.com/austindrenski) | [1](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.2.4+is%3Aclosed+assignee%3Aaustindrenski) - -### [Milestone 2.2.0](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.2.0) - -Contributor | Assigned issues --------------------------------------------------- | ----------------:| -[@austindrenski](https://github.com/austindrenski) | [15](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.2.0+is%3Aclosed+assignee%3Aaustindrenski) -[@roji](https://github.com/roji) | [8](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.2.0+is%3Aclosed+assignee%3Aroji) +# 2.2 Release Notes + +Version 2.2.0 of the Npgsql Entity Framework Core provider has been released and is available on nuget. This version works with [version 2.2.0 of Entity Framework Core](https://docs.microsoft.com/ef/core/what-is-new/ef-core-2.2), and contains some new Npgsql features as well. + +This release was result of hard work by [@roji](https://github.com/roji/), [@austindrenski](https://github.com/austindrenski), [@yohdeadfall](https://github.com/yohdeadfall) and [@khellang](https://github.com/khellang). + +## New Features + +Aside from general EF Core features new in 2.2.0, the Npgsql EF Core provider contains the following major new features: + +### PostgreSQL 11 covering indexes + +PostgreSQL 11 introduced [covering indexes feature](https://paquier.xyz/postgresql-2/postgres-11-covering-indexes), which allow you to include "non-key" columns in your indexes. This allows you to perform index-only scans and can provide a significant performance boost. Support has been added in ([#697](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/697)): + +```csharp +protected override void OnConfiguring(DbContextOptionsBuilder builder) + => modelBuilder.Entity() + .ForNpgsqlHasIndex(b => b.Id) + .ForNpgsqlInclude(b => b.Name); +``` + +This will create an index for searching on `Id`, but containing also the column `Name`, so that reading the latter will not involve accessing the table. [See the documentation for more details](../modeling/indexes.md). + +Thanks to [@khellang](https://github.com/khellang) for contributing this! + +### PostgreSQL user-defined ranges + +The provider already supported [PostgreSQL range types](https://www.postgresql.org/docs/current/rangetypes.html), but prior to 2.2 that support was limited to the built-in range types which come with PostgreSQL. [#329](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/329) extends that support to range types which you define: + +```csharp +protected override void OnConfiguring(DbContextOptionsBuilder builder) + => builder.UseNpgsql("...", b => b.MapRange("floatrange")); + +protected override void OnModelCreating(ModelBuilder builder) + => builder.ForNpgsqlHasRange("floatrange", "real"); +``` + +This will make the provider create a PostgreSQL range called `floatrange`, over the PostgreSQL type `real`. Any property with type `NpgsqlRange` will be seamlessly mapped to it. + +[See the documentation for more details](../mapping/range.md). + +### Seeding for Npgsql-specific types + +When using some Npgsql-specific types, it wasn't possible to seed values for those types. With EF Core support for seeding any type, [#667](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/667) allows seeding values for network, bit and range types (more are coming). + +### PostgreSQL index operator classes + +PostgreSQL allows you to specify [operator classes on your indexes](https://www.postgresql.org/docs/current/indexes-opclass.html), to allow tweaking how the index should work. [#481](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/481) adds support for managing these. [See the documentation for more details](../modeling/indexes.md). + +Thanks to [@khellang](https://github.com/khellang) for contributing this! + +### Other features + +* Various issues with enum and range types were fixed, including upper/lower case, quoting and schema management. +* Many new SQL translations were added, so more of your LINQ expressions can run in the database. We'll be working on our documentation to make these more discoverable. + +The full list of issues for this release is [available here](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues?q=milestone%3A2.2.0+is%3Aclosed&utf8=%E2%9C%93). + +## Contributors + +Thank you very much to the following people who have contributed to the individual 2.2.x. releases. + +### [Milestone 2.2.6](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.2.6) + +Contributor | Assigned issues +------------------------------------------------ | ----------------:| +[@roji](https://github.com/roji) |[5](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.2.6+is%3Aclosed+assignee%3Aroji) + +### [Milestone 2.2.4](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.2.4) + +Contributor | Assigned issues +-------------------------------------------------- | ----------------:| +[@roji](https://github.com/roji) | [3](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.2.4+is%3Aclosed+assignee%3Aroji) +[@austindrenski](https://github.com/austindrenski) | [1](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.2.4+is%3Aclosed+assignee%3Aaustindrenski) + +### [Milestone 2.2.0](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.2.0) + +Contributor | Assigned issues +-------------------------------------------------- | ----------------:| +[@austindrenski](https://github.com/austindrenski) | [15](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.2.0+is%3Aclosed+assignee%3Aaustindrenski) +[@roji](https://github.com/roji) | [8](https://github.com/npgsql/EFCore.PG/issues?q=is%3Aissue+milestone%3A2.2.0+is%3Aclosed+assignee%3Aroji) diff --git a/conceptual/Npgsql/copy.md b/conceptual/Npgsql/copy.md index 02c7ff2f..161b96a7 100644 --- a/conceptual/Npgsql/copy.md +++ b/conceptual/Npgsql/copy.md @@ -1,88 +1,88 @@ -# COPY - -PostgreSQL has a feature allowing efficient bulk import or export of data to and from a table. This is usually a much faster way of getting data in and out of a table than using INSERT and SELECT. See documentation for the [COPY command](http://www.postgresql.org/docs/current/static/sql-copy.html) for more details. - -Npgsql supports three COPY operation modes: binary, text and raw binary. - -## Binary COPY - -This mode uses the efficient PostgreSQL binary format to transfer data in and out of the database. The user uses an API to read and write rows and fields, which Npgsql decodes and encodes. When you've finished, you must call `Complete()` to save the data; not doing so will cause the COPY operation to be rolled back when the writer is disposed (this behavior is important in case an exception is thrown). - -> [!WARNING] -> It is the your responsibility to read and write the correct type! If you use COPY to write an int32 into a string field you may get an exception, or worse, silent data corruption. It is also highly recommended to use the overload of `Write()` which accepts an `NpgsqlDbType`, allowing you to unambiguously specify exactly what type you want to write. Test your code thoroughly. - -```csharp -// Import two columns to table data -using (var writer = conn.BeginBinaryImport("COPY data (field_text, field_int2) FROM STDIN (FORMAT BINARY)")) -{ - writer.StartRow(); - writer.Write("Hello"); - writer.Write(8, NpgsqlDbType.Smallint); - - writer.StartRow(); - writer.Write("Goodbye"); - writer.WriteNull(); - - writer.Complete(); -} - -// Export two columns to table data -using (var reader = Conn.BeginBinaryExport("COPY data (field_text, field_int2) TO STDOUT (FORMAT BINARY)")) -{ - reader.StartRow(); - Console.WriteLine(reader.Read()); - Console.WriteLine(reader.Read(NpgsqlDbType.Smallint)); - - reader.StartRow(); - reader.Skip(); - Console.WriteLine(reader.IsNull); // Null check doesn't consume the column - Console.WriteLine(reader.Read()); - - reader.StartRow(); // Last StartRow() returns -1 to indicate end of data -} -``` - -## Text COPY - -This mode uses the PostgreSQL text or csv format to transfer data in and out of the database. It is the user's responsibility to format the text or CSV appropriately, Npgsql simply provides a TextReader or Writer. This mode is less efficient than binary copy, and is suitable mainly if you already have the data in a CSV or compatible text format and don't care about performance. - -```csharp -using (var writer = conn.BeginTextImport("COPY data (field_text, field_int4) FROM STDIN")) { - writer.Write("HELLO\t1\n"); - writer.Write("GOODBYE\t2\n"); -} - -using (var reader = conn.BeginTextExport("COPY data (field_text, field_int4) TO STDOUT")) { - Console.WriteLine(reader.ReadLine()); - Console.WriteLine(reader.ReadLine()); -} -``` - -## Raw Binary COPY - -In this mode, data transfer is binary, but Npgsql does no encoding or decoding whatsoever - data is exposed as a raw .NET Stream. This mode makes sense only for bulk data and restore a table: the table is saved as a blob, which can later be restored. If you need to actually make sense of the data, you should be using regular binary mode instead (not raw). - -Example: - -```csharp -int len; -var data = new byte[10000]; -// Export table1 to data array -using (var inStream = conn.BeginRawBinaryCopy("COPY table1 TO STDOUT (FORMAT BINARY)")) { - // We assume the data will fit in 10000 bytes, in real usage you would read repeatedly, writine to a file. - len = inStream.Read(data, 0, data.Length); -} - -// Import data array into table2 -using (var outStream = conn.BeginRawBinaryCopy("COPY table2 FROM STDIN (FORMAT BINARY)")) { - outStream.Write(data, 0, len); -} -``` - -## Cancel - -Import operations can be cancelled at any time by disposing `NpgsqlBinaryImporter` without calling `Complete()` on it. Export operations can be cancelled as well, by calling `Cancel()`. - -## Other - -See the CopyTests.cs test fixture for more usage samples. +# COPY + +PostgreSQL has a feature allowing efficient bulk import or export of data to and from a table. This is usually a much faster way of getting data in and out of a table than using INSERT and SELECT. See documentation for the [COPY command](http://www.postgresql.org/docs/current/static/sql-copy.html) for more details. + +Npgsql supports three COPY operation modes: binary, text and raw binary. + +## Binary COPY + +This mode uses the efficient PostgreSQL binary format to transfer data in and out of the database. The user uses an API to read and write rows and fields, which Npgsql decodes and encodes. When you've finished, you must call `Complete()` to save the data; not doing so will cause the COPY operation to be rolled back when the writer is disposed (this behavior is important in case an exception is thrown). + +> [!WARNING] +> It is the your responsibility to read and write the correct type! If you use COPY to write an int32 into a string field you may get an exception, or worse, silent data corruption. It is also highly recommended to use the overload of `Write()` which accepts an `NpgsqlDbType`, allowing you to unambiguously specify exactly what type you want to write. Test your code thoroughly. + +```csharp +// Import two columns to table data +using (var writer = conn.BeginBinaryImport("COPY data (field_text, field_int2) FROM STDIN (FORMAT BINARY)")) +{ + writer.StartRow(); + writer.Write("Hello"); + writer.Write(8, NpgsqlDbType.Smallint); + + writer.StartRow(); + writer.Write("Goodbye"); + writer.WriteNull(); + + writer.Complete(); +} + +// Export two columns to table data +using (var reader = Conn.BeginBinaryExport("COPY data (field_text, field_int2) TO STDOUT (FORMAT BINARY)")) +{ + reader.StartRow(); + Console.WriteLine(reader.Read()); + Console.WriteLine(reader.Read(NpgsqlDbType.Smallint)); + + reader.StartRow(); + reader.Skip(); + Console.WriteLine(reader.IsNull); // Null check doesn't consume the column + Console.WriteLine(reader.Read()); + + reader.StartRow(); // Last StartRow() returns -1 to indicate end of data +} +``` + +## Text COPY + +This mode uses the PostgreSQL text or csv format to transfer data in and out of the database. It is the user's responsibility to format the text or CSV appropriately, Npgsql simply provides a TextReader or Writer. This mode is less efficient than binary copy, and is suitable mainly if you already have the data in a CSV or compatible text format and don't care about performance. + +```csharp +using (var writer = conn.BeginTextImport("COPY data (field_text, field_int4) FROM STDIN")) { + writer.Write("HELLO\t1\n"); + writer.Write("GOODBYE\t2\n"); +} + +using (var reader = conn.BeginTextExport("COPY data (field_text, field_int4) TO STDOUT")) { + Console.WriteLine(reader.ReadLine()); + Console.WriteLine(reader.ReadLine()); +} +``` + +## Raw Binary COPY + +In this mode, data transfer is binary, but Npgsql does no encoding or decoding whatsoever - data is exposed as a raw .NET Stream. This mode makes sense only for bulk data and restore a table: the table is saved as a blob, which can later be restored. If you need to actually make sense of the data, you should be using regular binary mode instead (not raw). + +Example: + +```csharp +int len; +var data = new byte[10000]; +// Export table1 to data array +using (var inStream = conn.BeginRawBinaryCopy("COPY table1 TO STDOUT (FORMAT BINARY)")) { + // We assume the data will fit in 10000 bytes, in real usage you would read repeatedly, writine to a file. + len = inStream.Read(data, 0, data.Length); +} + +// Import data array into table2 +using (var outStream = conn.BeginRawBinaryCopy("COPY table2 FROM STDIN (FORMAT BINARY)")) { + outStream.Write(data, 0, len); +} +``` + +## Cancel + +Import operations can be cancelled at any time by disposing `NpgsqlBinaryImporter` without calling `Complete()` on it. Export operations can be cancelled as well, by calling `Cancel()`. + +## Other + +See the CopyTests.cs test fixture for more usage samples. diff --git a/conceptual/Npgsql/large-objects.md b/conceptual/Npgsql/large-objects.md index d919ba42..a38d1534 100644 --- a/conceptual/Npgsql/large-objects.md +++ b/conceptual/Npgsql/large-objects.md @@ -1,38 +1,38 @@ -# Large Objects - -The Large Objects feature is a way of storing large files in a PostgreSQL database. Files can normally be stored in bytea columns but there are two downsides; a file can only be 1 GB and the backend buffers the whole file when reading or writing a column, which may use significant amounts of RAM on the backend. - -With the Large Objects feature, objects are instead stored in a separate system table in smaller chunks and provides a streaming API for the user. Each object is given an integral identifier that is used for accessing the object, that can, for example, be stored in a user's table containing information about this object. - -## Example - -```csharp -// Retrieve a Large Object Manager for this connection -var manager = new NpgsqlLargeObjectManager(Conn); - -// Create a new empty file, returning the identifier to later access it -uint oid = manager.Create(); - -// Reading and writing Large Objects requires the use of a transaction -using (var transaction = Conn.BeginTransaction()) -{ - // Open the file for reading and writing - using (var stream = manager.OpenReadWrite(oid)) - { - var buf = new byte[] { 1, 2, 3 }; - stream.Write(buf, 0, buf.Length); - stream.Seek(0, System.IO.SeekOrigin.Begin); - - var buf2 = new byte[buf.Length]; - stream.Read(buf2, 0, buf2.Length); - - // buf2 now contains 1, 2, 3 - } - // Save the changes to the object - transaction.Commit(); -} -``` - -## See also - -See the [PostgreSQL documentation](http://www.postgresql.org/docs/current/static/largeobjects.html) for more information. All functionality are implemented and wrapped in the classes `NpgsqlLargeObjectManager` and `NpgsqlLargeObjectStream` using standard .NET Stream as base class. +# Large Objects + +The Large Objects feature is a way of storing large files in a PostgreSQL database. Files can normally be stored in bytea columns but there are two downsides; a file can only be 1 GB and the backend buffers the whole file when reading or writing a column, which may use significant amounts of RAM on the backend. + +With the Large Objects feature, objects are instead stored in a separate system table in smaller chunks and provides a streaming API for the user. Each object is given an integral identifier that is used for accessing the object, that can, for example, be stored in a user's table containing information about this object. + +## Example + +```csharp +// Retrieve a Large Object Manager for this connection +var manager = new NpgsqlLargeObjectManager(Conn); + +// Create a new empty file, returning the identifier to later access it +uint oid = manager.Create(); + +// Reading and writing Large Objects requires the use of a transaction +using (var transaction = Conn.BeginTransaction()) +{ + // Open the file for reading and writing + using (var stream = manager.OpenReadWrite(oid)) + { + var buf = new byte[] { 1, 2, 3 }; + stream.Write(buf, 0, buf.Length); + stream.Seek(0, System.IO.SeekOrigin.Begin); + + var buf2 = new byte[buf.Length]; + stream.Read(buf2, 0, buf2.Length); + + // buf2 now contains 1, 2, 3 + } + // Save the changes to the object + transaction.Commit(); +} +``` + +## See also + +See the [PostgreSQL documentation](http://www.postgresql.org/docs/current/static/largeobjects.html) for more information. All functionality are implemented and wrapped in the classes `NpgsqlLargeObjectManager` and `NpgsqlLargeObjectStream` using standard .NET Stream as base class. diff --git a/conceptual/Npgsql/wait.md b/conceptual/Npgsql/wait.md index 89092732..b8303bf0 100644 --- a/conceptual/Npgsql/wait.md +++ b/conceptual/Npgsql/wait.md @@ -1,45 +1,45 @@ -# Waiting for Notifications - -Note: *This functionality replaces Npgsql 3.0's "Continuous processing mode"*. - -## PostgreSQL Asynchronous messages - -PostgreSQL has a feature whereby arbitrary notification messages can be sent between clients. For example, one client may wait until it is -notified by another client of a task that it is supposed to perform. Notifications are, by their nature, asynchronous - they can arrive -at any point. For more detail about this feature, see the PostgreSQL [NOTIFY command](http://www.postgresql.org/docs/current/static/sql-notify.html). -Some other asynchronous message types are notices (e.g. database shutdown imminent) and parameter changes, see the -[PostgreSQL protocol docs](http://www.postgresql.org/docs/current/static/protocol-flow.html#PROTOCOL-ASYNC) for more details. - -Note that despite the word "asynchronous", this page has nothing to do with ADO.NET async operations (e.g. ExecuteReaderAsync). - -## Processing of Notifications - -Npgsql exposes notification messages via the `Notification` event on NpgsqlConnection. - -Since asynchronous notifications are rarely used and processing can be complex, Npgsql only processes notification messages as -part of regular (synchronous) query interaction. That is, if an asynchronous notification is sent, Npgsql will only process it and emit an -event to the user the next time a command is sent and processed. - -To receive notifications outside a synchronous request-response cycle, call `NpgsqlConnection.Wait()`. This will make your thread block -until a single notification is received (note that a version with a timeout as well as an async version exist). Note that the notification -is still delivered via the `Notification` event as before. - -```csharp -var conn = new NpgsqlConnection(ConnectionString); -conn.Open(); -conn.Notification += (o, e) => Console.WriteLine("Received notification"); - -using (var cmd = new NpgsqlCommand("LISTEN channel_name", conn)) { - cmd.ExecuteNonQuery(); -} - -while (true) { - conn.Wait(); // Thread will block here -} -``` - ---- - -## Keepalive - -You may want to turn on [keepalives](keepalive.md). +# Waiting for Notifications + +Note: *This functionality replaces Npgsql 3.0's "Continuous processing mode"*. + +## PostgreSQL Asynchronous messages + +PostgreSQL has a feature whereby arbitrary notification messages can be sent between clients. For example, one client may wait until it is +notified by another client of a task that it is supposed to perform. Notifications are, by their nature, asynchronous - they can arrive +at any point. For more detail about this feature, see the PostgreSQL [NOTIFY command](http://www.postgresql.org/docs/current/static/sql-notify.html). +Some other asynchronous message types are notices (e.g. database shutdown imminent) and parameter changes, see the +[PostgreSQL protocol docs](http://www.postgresql.org/docs/current/static/protocol-flow.html#PROTOCOL-ASYNC) for more details. + +Note that despite the word "asynchronous", this page has nothing to do with ADO.NET async operations (e.g. ExecuteReaderAsync). + +## Processing of Notifications + +Npgsql exposes notification messages via the `Notification` event on NpgsqlConnection. + +Since asynchronous notifications are rarely used and processing can be complex, Npgsql only processes notification messages as +part of regular (synchronous) query interaction. That is, if an asynchronous notification is sent, Npgsql will only process it and emit an +event to the user the next time a command is sent and processed. + +To receive notifications outside a synchronous request-response cycle, call `NpgsqlConnection.Wait()`. This will make your thread block +until a single notification is received (note that a version with a timeout as well as an async version exist). Note that the notification +is still delivered via the `Notification` event as before. + +```csharp +var conn = new NpgsqlConnection(ConnectionString); +conn.Open(); +conn.Notification += (o, e) => Console.WriteLine("Received notification"); + +using (var cmd = new NpgsqlCommand("LISTEN channel_name", conn)) { + cmd.ExecuteNonQuery(); +} + +while (true) { + conn.Wait(); // Thread will block here +} +``` + +--- + +## Keepalive + +You may want to turn on [keepalives](keepalive.md).