Skip to content

Commit

Permalink
Merge branch 'rel/1.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
roji committed Nov 20, 2016
2 parents 9804025 + 4f804d4 commit 39c93a6
Show file tree
Hide file tree
Showing 132 changed files with 7,254 additions and 1,398 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
</runner>
<runner id="RUNNER_25" name="Build Debug" type="simpleRunner">
<parameters>
<param name="script.content"><![CDATA[set KOREBUILD_DOTNET_PACK_OPTIONS=--version-suffix "%build.counter%"
<param name="script.content"><![CDATA[set KOREBUILD_DOTNET_PACK_OPTIONS= --version-suffix "%build.counter%"
set Configuration=Debug
build compile]]></param>
<param name="teamcity.step.mode" value="default" />
Expand All @@ -36,7 +36,7 @@ build compile]]></param>
</runner>
<runner id="RUNNER_27" name="Build Release" type="simpleRunner">
<parameters>
<param name="script.content"><![CDATA[set KOREBUILD_DOTNET_PACK_OPTIONS=--version-suffix "%build.counter%"
<param name="script.content"><![CDATA[set KOREBUILD_DOTNET_PACK_OPTIONS= --version-suffix "%build.counter%"
set Configuration=Release
build compile]]></param>
<param name="teamcity.step.mode" value="default" />
Expand Down
1 change: 0 additions & 1 deletion NuGet.Config
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,5 @@
</packageRestore>
<packageSources>
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
<add key="AspNetCore" value="https://dotnet.myget.org/F/aspnetcore-master/api/v3/index.json" />
</packageSources>
</configuration>
56 changes: 56 additions & 0 deletions doc/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Getting Started

Npgsql has an Entity Framework Core provider. It mostly behaves like a any other EFCore provider (e.g. SQL Server) - all the information in the [general EF Core docs](https://docs.microsoft.com/en-us/ef/core/index) applies. If you're just getting started with EF Core, those docs are the best place to start.

Development happens in the [Npgsql.EntityFrameworkCore.PostgreSQL](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL) repository, all issues should be reported there.

## Using the Npgsql EF Core Provider

To use the Npgsql EF Core provider, simply add a dependency on `Npgsql.EntityFrameworkCore.PostgreSQL`. You can follow the instructions in the general [EF Core Getting Started docs](https://docs.microsoft.com/en-us/ef/core/get-started/).

Following is an example project.json using Npgsql EF Core:

```json
{
"version": "1.0.0-*",
"buildOptions": {
"debugType": "portable",
"emitEntryPoint": true
},
"dependencies": {
"Npgsql.EntityFrameworkCore.PostgreSQL": "1.0.2",
"Microsoft.EntityFrameworkCore.Design": {
"version": "1.0.0-preview2-final",
"type": "build"
}
},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
},
"imports": "dnxcore50"
}
},
"tools": {
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"
}
}
```

## Using an Existing Database (Database-First)

The Npgsql EF Core provider also supports reverse-engineering a code model from an existing PostgreSQL database ("database-first"). To do so, add a dependency on Npgsql.EntityFrameworkCore.PostgreSQL.Design. Then, execute the following if you're using dotnet cli:

```bash
Scaffold-DbContext "Host=localhost;Database=mydatabase;Username=myuser;Password=mypassword" Npgsql.EntityFrameworkCore.PostgreSQL
```

Or with Powershell:

```powershell
Scaffold-DbContext "Host=localhost;Database=mydatabase;Username=myuser;Password=mypassword" Npgsql.EntityFrameworkCore.PostgreSQL
```
45 changes: 45 additions & 0 deletions doc/mapping-and-translation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
## Type Mapping

The EF Core provider can transparently map any type supported by Npgsql at the ADO.NET level. This means you can use PostgreSQL-specific types, such as `inet` or `circle`, directly in your entities - this wasn't possible in EF 6.x. Simply define your properties just as if they were a simple type, such as a string:

```c#
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; }
}
```

Note that mapping array properties to [PostgreSQL arrays](https://www.postgresql.org/docs/current/static/arrays.html) is supported. However, operations such as indexing the array, searching for elements in it, etc. aren't yet translated to SQL and will be evaluated client-side. This will probably be fixed in 1.2.

[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 Datatypes (e.g. JSON)

In some cases, your .NET property type can be mapped to several PostgreSQL datatypes; a good example is a string, which will be mapped to `text` by default, but can also be mapped to `jsonb`. You can explicitly specify the PostgreSQL datatype by adding the following to your model's `OnModelCreating`:

```c#
builder.Entity<Blog>()
.Property(b => b.SomeStringProperty)
.HasColumnType("jsonb");
```

Or, if you prefer annotations, use the `[Column]` attribute:

```c#
[Column(TypeName="jsonb")]
public string SomeStringProperty { get; set; }
```

## Translating Regular Expressions

PostgreSQL supports [regular expression operations in the database](http://www.postgresql.org/docs/current/static/functions-matching.html#FUNCTIONS-POSIX-REGEXP), and the Npgsql EF Core provider provides some support for evaluating C# regex operations at the backend. All you have to do is use `Regex.IsMatch` in your where clause:

```c#
var customersStartingWithA = context.Customers.Where(c => Regex.IsMatch(c.CompanyName, "^A"));
```

Since this regular expression is evaluated at the server, the EF Core provider doesn't need to load all the customers from the database, saving lots of transfer bandwidth.
30 changes: 30 additions & 0 deletions doc/migration/1.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Migrating to 1.1 (in preview)

Version 1.1.0-preview1 of the Npgsql Entity Framework Core provider has been released and is available on nuget. This version works with the [recently released 1.1.0-preview1 of Entity Framework Core](https://blogs.msdn.microsoft.com/dotnet/2016/10/25/announcing-entity-framework-core-1-1-preview-1/), and contains some new Npgsql features as well. Note that if you're using the command-line tools, you'll have to modify your tools section as described in the EF Core release post:

```json
"tools": {
"Microsoft.EntityFrameworkCore.Tools.DotNet": "1.0.0-preview3-final"
},
```

## New Features

Aside from general EF Core features, version 1.1.0 of the Npgsql provider contains the following:

* Hilo key generation ([#5](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/5)). This can be a much more efficient way to generate autoincrement key values.
* PostgreSQL array mapping ([#15](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/15)). This allows you to have plain CLR arrays on your entities, and have those arrays mapped to native [PostgreSQL array columns](https://www.postgresql.org/docs/current/static/arrays.html).
* Optimistic concurrency with PostgreSQL's xmin column ([#19](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/19)). Simply specify `.UseXminAsConcurrencyToken()` on an entity to start using this, see the [EF docs for more details](https://docs.efproject.net/en/latest/modeling/concurrency.html).
* Cleanup of how serial (autoincrement) and generated GUID/UUID columns are managed.

Here's the [full list of issues](https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/milestone/3?closed=1). Please report any problems to https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL.

## Upgrading from 1.0.x

If you've used 1.0.x without migrations, you can simply upgrade and everything should just work. Unfortunately, if you already have migrations from 1.0.x you'll have to do some manual fixups because of some bad decisions that were previously made. If deleting your old migrations and starting over (e.g. non-production database) is an option you may wish to do so. The following are instructions for fixing up 1.0.x migrations.

First, Npgsql 1.0.x used a problematic method to identify serial (autoincrement) columns in migrations. If you look at your migration code you'll see `.Annotation("Npgsql:ValueGeneratedOnAdd", true)` on various columns. Unfortunately this annotation is also present non-serial columns, e.g. columns with default values. This causes various issues and has been replaced in 1.1. However, you'll have to remove `.Annotation("Npgsql:ValueGeneratedOnAdd", true)`, and replacing it with `.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)` but *only* on columns which should be serial (e.g. not on columns with defaults). If you attempt to run a migration that has the old annotation, Npgsql will throw an exception and refuse to run your migrations.

Unfortunately, this change will cause some incorrect changes the first time you add a migration after the upgrade. To avoid this, simply add a dummy migration right after upgrading to 1.1 and then delete the two new migration files, but keeping the changes made to your ModelSnapshot.cs. From this point on everything should be fine. *Make sure you have no pending changes to your model before doing this!*.

Apologies for this problematic upgrade procedure, it should at least keep things clean going forward.
34 changes: 34 additions & 0 deletions doc/misc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Misc

## Setting up PostgreSQL extensions

The provider allows you to specify PostgreSQL extensions that should be set up in your database.
Simply use HasPostgresExtension in your context's OnModelCreating:

```c#
protected override void OnModelCreating(ModelBuilder modelBuilder) {
modelBuilder.HasPostgresExtension("hstore");
}
```

## Optimistic Concurrency and Concurrency Tokens

Entity Framework supports the concept of optimistic concurrency - a property on your entity is designated as a concurrency token, and EF detects concurrent modifications by checking whether that token has changed since the entity was read. You can read more about this in the [EF docs](https://docs.microsoft.com/en-us/ef/core/modeling/concurrency).

Although applications can update concurrency tokens themselves, we frequently rely on the database automatically updating a column on update - a "last modified" timestamp, an SQL Server `rowversion`, etc. Unfortunately PostgreSQL doesn't have such auto-updating columns - but there is one feature that can be used for concurrency token. All PostgreSQL have a set of [implicit and hidden system columns](https://www.postgresql.org/docs/current/static/ddl-system-columns.htm://www.postgresql.org/docs/current/static/ddl-system-columns.html), among which `xmin` holds the ID of the latest updating transaction. Since this value automatically gets updated every time the row is changed, it is ideal for use as a concurrency token.

To enable this feature on an entity, insert the following code into your models' `OnModelCreating` method:

```c#
modelBuilder.Entity<MyEntity>().ForNpgsqlUseXminAsConcurrencyToken();
```

## Using a database template

When creating a new database,
[PostgreSQL allows specifying another "template database"](http://www.postgresql.org/docs/current/static/manage-ag-templatedbs.html)
which will be copied as the basis for the new one. This can be useful for including database entities which aren't managed by Entity Framework. You can trigger this by using HasDatabaseTemplate in your context's `OnModelCreating`:

```c#
modelBuilder.HasDatabaseTemplate("my_template_db");
```
6 changes: 6 additions & 0 deletions doc/toc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# [Getting Started](index.md)
# Migration Notes
## [From 1.0.x to 1.1.x](migration/1.1.md)
# [Value Generation](value-generation.md)
# [Mapping and Translation](mapping-and-translation.md)
# [Miscellaneous](misc.md)
48 changes: 48 additions & 0 deletions doc/value-generation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Value Generation

See [the general EF Docs on value generation](https://docs.microsoft.com/en-us/ef/core/modeling/generated-properties) to better understand the concepts described here.

## Serial (Autoincrement) Columns

In PostgreSQL, the standard autoincrement column type is called `serial`. This isn't really a special type like in some other databases (e.g. SQL Server's IDENTITY), but rather a shorthand for specifying that the column's default value should come from a sequence. See [the PostgreSQL docs](https://www.postgresql.org/docs/current/static/datatype-numeric.html#DATATYPE-SERIAL) for more info.

When `ValueGeneratedOnAdd` is specified on a short, int or long property, the Npgsql EF Core provider will automatically map it to a `serial` 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`.

Note that there was a significant and breaking change in 1.1. If you have existing migrations generated with 1.0, please read the [migration notes](migration/1.1.md).

## HiLo Autoincrement Generation

One disadvantage of database-generated values is that these values must be read back from the database after a row is inserted. If you're saving multiple related entities, this means you must perform multiple roundtrips as the first entity's generated key must be read before writing the second one. One solution to this problem is HiLo value generation: rather than relying on the database to generate each and every value, the application "allocates" a range of values, which it can then populate directly on new entities without any additional roundtrips. When the range is exhausted, a new range is allocated. In practical terms, this uses a sequence that increments by some large value (100 by default), allowing the application to insert 100 rows autonomously.

To use HiLo, specify `ForNpgsqlUseSequenceHiLo` on a property in your model's `OnModelCreating`:

```c#
modelBuilder.Entity<Blog>().Property(b => b.Id).ForNpgsqlUseSequenceHiLo();
```

You can also make your model use HiLo everywhere:

```c#
modelBuilder.ForNpgsqlUseSequenceHiLo();
```

## Guid/UUID Generation

By default, if you specify `ValueGeneratedOnAdd` on a Guid property, a random Guid value will be generated client-side and sent to the database.

If you prefer to generate values in the database instead, you can do so by specifying `HasDefaultValueSql` on your property. Note that PostgreSQL doesn't include any Guid/UUID generation functions, you must add an extension such as `uuid-ossp` or `pgcrypto`. This can be done by placing the following code in your model's `OnModelCreating`:

```c#
modelBuilder.HasPostgresExtension("uuid-ossp");
modelBuilder
.Entity<Blog>()
.Property(e => e.SomeGuidProperty)
.HasDefaultValueSql("uuid_generate_v4()");
```

See [the PostgreSQL docs on UUID for more details](https://www.postgresql.org/docs/current/static/datatype-uuid.html).

## Computed Columns (On Add or Update)

PostgreSQL does not support computed columns.

5 changes: 4 additions & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{
"projects": [ "src", "test" ]
"projects": [ "src", "test" ],
"sdk": {
"version": "1.0.0-preview2-003131"
}
}
Loading

0 comments on commit 39c93a6

Please sign in to comment.