You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 53262dd
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: conceptual/EFCore.PG/mapping/json.md
+19-5Lines changed: 19 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -57,13 +57,13 @@ With string mapping, the EF Core provider will save and load properties to datab
57
57
58
58
If your column JSON contains documents with a stable schema, you can map them to your own .NET types (or POCOs); EF will use System.Text.Json APIs under the hood to serialize instances of your types to JSON documents before sending them to the database, and to deserialize documents coming back from the database. This effectively allows mapping an arbitrary .NET type - or object graph - to a single column in the database.
59
59
60
-
EF 7.0 introduced the "JSON Columns" feature, which maps a database JSON column via EF's "owned entity" mapping concept, using `ToJson()`. In this approach, EF fully models the types within the JSON document - just like it models regular tables and columns - and uses that information to perform better queries and updates. Full support for ToJson has been added to version 8.0 of the Npgsql EF provider.
60
+
As of EF 10, the recommended way to map .NET types to JSON in the database is via complex types ([see EF release notes](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-10.0/whatsnew#json)). In this mode, EF is fully aware of the structure of your JSON document - just like it's aware of your tables and columns - and provides powerful, rich querying and updating capabilities. Prior to EF 10, similar modeling was available via the "owned entity" concept, but this modeling created several issues ([see here for more details](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-10.0/whatsnew#json)). If you're using EF 10 or above, complex types are the recommended way to map .NET types.
61
61
62
-
As an alternative, prior to version 8.0, the Npgsql EF provider has supported JSON POCO mapping by simply delegating serialization/deserialization to System.Text.Json; in this model, EF itself model the contents of the JSON document, and cannot take that structure into account for queries and updates. This approach can now be considered deprecated as it allows for less powerful mapping and supports less query types; using ToJson() is now the recommended way to map POCOs to JSON.
62
+
As an 3rd alternative, prior to version 8.0, the Npgsql EF provider has supported JSON POCO mapping by simply delegating serialization/deserialization to System.Text.Json; in this mode, EF itself is oblivious to the contents of the JSON document, and cannot take that structure into account for queries and updates. This approach can now be considered deprecated as it allows for less powerful mapping and supports less query types; using complex types with `ToJson()` is now the recommended way to map POCOs to JSON.
63
63
64
-
### ToJson (owned entity mapping)
64
+
### EF modeling with ToJson (recommended)
65
65
66
-
Npgsql's support for `ToJson()` is fully aligned with the general EF support; see the [EF documentation for more information](https://learn.microsoft.com/ef/core/what-is-new/ef-core-7.0/whatsnew#json-columns).
66
+
Npgsql's support for `ToJson()` is fully aligned with the general EF support; see the [EF documentation for more information](https://learn.microsoft.com/ef/core/what-is-new/ef-core-10.0/whatsnew#json).
67
67
68
68
To get you started quickly, assume that we have the following Customer type, with a Details property that we want to map to a single JSON column in the database:
69
69
@@ -90,6 +90,18 @@ public class Order // Part of the JSON column
90
90
91
91
To instruct EF to map CustomerDetails - and within it, Order - to a JSON column, configure it as follows:
At this point you can interact with the Customer just like you would normally, and EF will seamlessly serialize and deserialize it to a JSON column in the database. You can also perform LINQ queries which reference properties inside the JSON document, and these will get translated to SQL.
106
120
107
121
### Legacy POCO mapping (deprecated)
@@ -134,7 +148,7 @@ public class Order // Part of the JSON column
Copy file name to clipboardExpand all lines: conceptual/EFCore.PG/release-notes/10.0.md
+117-1Lines changed: 117 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,6 +2,119 @@
2
2
3
3
Npgsql.EntityFrameworkCore.PostgreSQL version 10.0 is now in development, preview versions are available on [nuget.org](https://www.nuget.org/packages/Npgsql.EntityFrameworkCore.PostgreSQL).
4
4
5
+
## Full support for EF 10 JSON complex types
6
+
7
+
EF 10 introduced support for mapping .NET types as JSON complex types, resolving several issues that existed with the previous JSON mapping via owned entities ([see release notes for more information](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-10.0/whatsnew#json)). The PG provider providers full support for this feature full support for this as well:
This configuration causes the following table to be created for your customers:
18
+
19
+
```sql
20
+
CREATETABLE "Customers" (
21
+
"Id"integer GENERATED BY DEFAULT AS IDENTITY,
22
+
"Name"text,
23
+
"BillingAddress" jsonb NOT NULL,
24
+
"ShippingAddress" jsonb NOT NULL,
25
+
CONSTRAINT"PK_Customers"PRIMARY KEY ("Id")
26
+
);
27
+
```
28
+
29
+
This is now the preferred way to perform strongly-typed JSON mapping of arbitrary .NET types, and replaces owned entities and [legacy POCO mapping](../mapping/json.md?#legacy-poco-mapping-deprecated).
30
+
31
+
The provider now also supports performing partial updates within JSON documents using `ExecuteUpdate`. For example, the following efficiently copies overwrites all Customers' shipping address streets with their billing address streets:
## Better support for JSON scalar (primitive) collections
46
+
47
+
In most relational databases, scalar collections are mapped to a JSON column, the the collection is serialized to a JSON array in the database. PostgreSQL, however, is unique in providing a 1st-class array type, so the EF provider maps scalar collections to array instead. For example, given the following type:
48
+
49
+
```c#
50
+
publicclassCustomer
51
+
{
52
+
publicintId { get; set; }
53
+
publicstring[] Tags { get; set; }
54
+
}
55
+
```
56
+
57
+
... the PostgreSQL provider will create the following table (note that `text[]` array column):
58
+
59
+
```sql
60
+
CREATETABLE "Customers" (
61
+
"Id"integer GENERATED BY DEFAULT AS IDENTITY,
62
+
"Tags"text[] NOT NULL,
63
+
CONSTRAINT"PK_Customers"PRIMARY KEY ("Id")
64
+
);
65
+
```
66
+
67
+
However, when scalar collections are nested within a JSON document, they must be mapped to JSON arrays, as in other databases:
68
+
69
+
```c#
70
+
publicclassCustomer
71
+
{
72
+
publicintId { get; set; }
73
+
publicAddressAddress { get; set; }
74
+
}
75
+
76
+
publicclassAddress
77
+
{
78
+
// ...
79
+
80
+
publicstring[] Tags { get; set; }
81
+
}
82
+
```
83
+
84
+
Version 10 of the provider now produces much better SQL when querying such nested scalar collections. For example, when querying using Contains:
... previous versions of the provider generated the following complicated (and inefficient) SQL:
91
+
92
+
```sql
93
+
SELECT c."Id", c."Name", c."ShippingAddress"
94
+
FROM"Customers"AS c
95
+
WHERE'foo'= ANY ((ARRAY(SELECT CAST(element AStext) FROM jsonb_array_elements_text(c."ShippingAddress"->'Tags') WITH ORDINALITY AS t(element) ORDER BY ordinality)))
96
+
```
97
+
98
+
Version 10, in contrast, produces the following cleaner SQL, which can also benefit from indexes:
99
+
100
+
```sql
101
+
SELECT c."Id", c."Name", c."ShippingAddress"
102
+
FROM"Customers"AS c
103
+
WHERE (c."ShippingAddress"->'Tags') @> to_jsonb('foo'::text)
104
+
```
105
+
106
+
Finally, version 10 of the provider also allows you to map a non-nested scalar collection to a JSON column, instead of to an array column, and provides fully querying capabilities:
107
+
108
+
```c#
109
+
publicclassCustomer
110
+
{
111
+
// ...
112
+
113
+
[Column(TypeName="jsonb")]
114
+
publicstring[] Tags { get; set; }
115
+
}
116
+
```
117
+
5
118
## Support for PostgreSQL 8 virtual generated columns
6
119
7
120
Before PostgreSQL 18, generated (or "computed") columns could only be stored, meaning they were computed when a row is inserted or updated, and take up space on disk just like regular columns. PostgreSQL 18 introduced support for *virtual* generated columns, which are instead calculated when read, and take up no space on disk. Virtual columns can be defined with version 10 of the PostgreSQL provider as follows:
@@ -19,9 +132,12 @@ Note that previously, `stored: true` had to be specified in the above code sampl
19
132
20
133
For more information, [see the documentation](../modeling/generated-properties.md#computed-generated-columns).
21
134
135
+
## Support for UUIDv7
136
+
137
+
By default, EF generates GUID (or UUID) values locally in .NET, rather than relying on the database to generate them. Version 9 of the PG provider already switched to generating UUIDv7 values by default ([see release note](9.0.md#uuidv7-guids-are-generated-by-default)), which are significantly better for database indexes. PostgreSQL 18 also added the [`uuidv7()`](https://www.postgresql.org/docs/18/functions-uuid.html#FUNC_UUID_GEN_TABLE) built-in function, which allows database generation of UUIDv7 values. In EFCore.PG 10, if you configure the provider to target PG 18 (`.UseNpgsql("...", o => o.SetPostgresVersion(18, 0))`), the provider will also translate [`Guid.CreateVersion7()`](https://learn.microsoft.com/dotnet/api/system.guid.createversion7) to that function.
138
+
22
139
## Other new features
23
140
24
-
* When the target PostgreSQL is version is set to 18 (`.UseNpgsql("...", o => o.SetPostgresVersion(18, 0))`), translate [`Guid.CreateVersion7()`](https://learn.microsoft.com/dotnet/api/system.guid.createversion7) to the new [`uuidv7()`](https://www.postgresql.org/docs/18/functions-uuid.html) function.
25
141
* NodaTime `LocalDate.At()` and `LocalDate.AtMidnight()` are now translated.
26
142
27
143
See the [10.0.0 milestone](https://github.com/npgsql/efcore.pg/milestone/68?closed=1) for the full list of Npgsql EF provider issues.
0 commit comments