-
Notifications
You must be signed in to change notification settings - Fork 226
Settings.AddJsonColumnMappings
Maps a JSON column to a real C# class instead of leaving it as a string.
| Type | Action<List<JsonColumnMapping>> |
| Default | Adds nothing |
| Applies to | EF Core mainly; ToJson() needs EF Core 7+ |
| Databases | SQL Server (json, nvarchar), PostgreSQL (json, jsonb), MySQL (json) |
In Database.tt? |
Yes, with commented-out examples |
A JSON column arrives as a string, because that is what it is at the database level. That is honest and
useless - you end up deserialising it by hand at every call site.
This setting tells the generator that a particular column holds a particular shape, so the property is typed as that class:
Settings.AddJsonColumnMappings = delegate(List<JsonColumnMapping> jsonColumnMappings)
{
jsonColumnMappings.Add(new JsonColumnMapping
{
Schema = "dbo",
Table = "Orders",
Column = "ShippingAddress",
PropertyType = "Address",
AdditionalNamespace = "MyApp.Models"
});
// Wildcards work on schema and table
jsonColumnMappings.Add(new JsonColumnMapping
{
Schema = "*",
Table = "*",
Column = "Metadata",
PropertyType = "Dictionary<string, object>"
});
};JsonColumnMapping has six fields:
| Field | Purpose |
|---|---|
Schema |
Schema name, or "*"
|
Table |
Table name, or "*"
|
Column |
The column to map |
PropertyType |
The C# type, written verbatim |
AdditionalNamespace |
A using to add for that type |
ExcludePropertyConfiguration |
Suppresses the generated builder.Property(...) line - see below |
Set it true when you intend to configure the property yourself with OwnsOne(...).ToJson(), EF Core 7's
way of mapping a JSON column to an owned type that can be queried into.
The generator's own builder.Property(...) line and your OwnsOne block cannot both configure the same
property, so this is how you turn the first one off:
jsonColumnMappings.Add(new JsonColumnMapping
{
Schema = "dbo",
Table = "Orders",
Column = "ShippingAddress",
PropertyType = "Address",
ExcludePropertyConfiguration = true // I will do the OwnsOne(...).ToJson() myself
});Any JSON column with a stable shape. If the same keys are always there, a type is better than a string.
Dictionary<string, object> for genuinely free-form JSON, which at least saves the deserialisation call.
Leave it alone for JSON you never read in C# - an audit blob, a payload passed through to somewhere else.
A string is the right type for something you do not look inside.
You still need a converter, unless you use ToJson(). Typing the property as Address does not tell EF
how to turn the column's text into one. Either supply a value converter in a partial OnModelCreatingPartial,
or use the OwnsOne(...).ToJson() route with ExcludePropertyConfiguration = true. Without one of the two,
the model will not build at run time - and the generated code compiles perfectly, so you find out late.
PropertyType is written verbatim and not validated. The class must exist, and you must write it - the
generator does not produce it. This is the opposite of
Settings.AddOwnedEntityMappings, which does generate the class.
AdditionalNamespace is per mapping, unlike the global
Settings.AdditionalNamespaces. Both work; the per-mapping one keeps the
using off files that do not need it.
Wildcards match broadly. Schema = "*", Table = "*", Column = "Metadata" catches every Metadata
column in the database, including ones that are not JSON.
ToJson() needs EF Core 7 or later and has real query limitations - you cannot index into a JSON
collection in a WHERE clause on every provider.
It relies on Settings.ApplyJsonColumnMappings being called from
Settings.UpdateColumn, which the shipped Database.tt does. Replace UpdateColumn
and drop that call, and this setting silently stops working.
-
JSON column support - the full page, with converters and
ToJson()worked through - Settings.AddOwnedEntityMappings - the other route to a nested type, where the class is generated
-
Settings.UpdateColumn - where
ApplyJsonColumnMappingsis called - Settings Reference
- Settings A-Z - every setting, with a page each
- Common Settings Types Explained
- Settings Callbacks
- Settings runtime values and helpers
- Filtering
- Full Control Over the Generated Code
- Enum Generation from Table Data
- Owned Entities
- JSON column support
- Global Query Filters
- Extended Property Names Feature
- Partial Properties
- File-Scoped Namespaces
- Data Annotations
- Spatial Types
- HierarchyId
- RowVersion and TimeStamp columns
- Lazy Loading
- Stored proc result sets
- Custom File-Based Templates
- Extra entities via partial classes
- INotifyPropertyChanged
- Syntax colour for T4