Skip to content

Commit 49c3da9

Browse files
ajcvickersdivega
authored andcommitted
Value conversion docs
Issue #614
1 parent 0858f15 commit 49c3da9

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
---
2+
title: Value Conversions - EF Core
3+
author: ajcvickers
4+
ms.author: divega
5+
6+
ms.date: 02/19/2018
7+
8+
ms.assetid: 3154BF3C-1749-4C60-8D51-AE86773AA116
9+
ms.technology: entity-framework-core
10+
11+
uid: core/modeling/value-conversions
12+
---
13+
# Value Conversions
14+
15+
> [!NOTE]
16+
> This feature is new in EF Core 2.1.
17+
18+
Value converters allow property values to be converted when reading from or writing to the database. This conversion can be from one value to another of the same type (for example, encrypting strings) or from a value of one type to a value of another type (for example, converting enum values to and from strings in the database.)
19+
20+
## Fundamentals
21+
22+
Value converters are specified in terms of a `ModelClrType` and a `ProviderClrType`. The model type is the .NET type of the property in the entity type. The provider type is the .NET type understood by the database provider. For example, to save enums as strings in the database, the model type is the type of the enum, and the provider type is `String`. These two types can be the same.
23+
24+
Conversions are defined using two `Func` expression trees: one from `ModelClrType` to `ProviderClrType` and the other from `ProviderClrType` to `ModelClrType`. Expression trees are used so that they can be compiled into the database access code for efficient conversions. For complex conversions, the expression tree may be a simple call to a method that performs the conversion.
25+
26+
## Configuring a value converter
27+
28+
Value conversions are defined on properties in the OnModelCreating of your DbContext. For example, consider an enum and entity type defined as:
29+
```C#
30+
public class Rider
31+
{
32+
public int Id { get; set; }
33+
public EquineBeast Mount { get; set; }
34+
}
35+
36+
public enum EquineBeast
37+
{
38+
Donkey,
39+
Mule,
40+
Horse,
41+
Unicorn
42+
}
43+
```
44+
Then conversions can be defined in OnModelCreating to store the enum values as strings (e.g. "Donkey", "Mule", ...) in the database:
45+
```C#
46+
protected override void OnModelCreating(ModelBuilder modelBuilder)
47+
{
48+
modelBuilder
49+
.Entity<Rider>()
50+
.Property(e => e.Mount)
51+
.HasConversion(
52+
v => v.ToString(),
53+
v => (EquineBeast)Enum.Parse(typeof(EquineBeast), v));
54+
}
55+
```
56+
> [!NOTE]
57+
> A `null` value will never be passed to a value converter. This makes the implementation of conversions easier and allows them to be shared amongst nullable and non-nullable properties.
58+
59+
## The ValueConverter class
60+
61+
Calling `HasConversion` as shown above will create a `ValueConverter` instance and set it on the property. The `ValueConverter` can instead be created explicitly. For example:
62+
```C#
63+
var converter = new ValueConverter<EquineBeast, string>(
64+
v => v.ToString(),
65+
v => (EquineBeast)Enum.Parse(typeof(EquineBeast), v));
66+
67+
modelBuilder
68+
.Entity<Rider>()
69+
.Property(e => e.Mount)
70+
.HasConversion(converter);
71+
```
72+
This can be useful when multiple properties use the same conversion.
73+
74+
> [!NOTE]
75+
> There is currently no way to specify in one place that every property of a given type must use the same value converter. This feature will be considered for a future release.
76+
77+
## Built-in converters
78+
79+
EF Core ships with a set of pre-defined `ValueConverter` classes, found in the `Microsoft.EntityFrameworkCore.Storage.Converters` namespace. These are:
80+
* `BoolToZeroOneConverter` - Bool to zero and one
81+
* `BoolToStringConverter` - Bool to strings such as "Y" and "N"
82+
* `BoolToTwoValuesConverter` - Bool to any two values
83+
* `BytesToStringConverter` - Byte array to Base64-encoded string
84+
* `CastingConverter` - Conversions that require only a C# cast
85+
* `CharToStringConverter` - Char to single character string
86+
* `DateTimeOffsetToBinaryConverter` - DateTimeOffset to binary-encoded 64-bit value
87+
* `DateTimeOffsetToBytesConverter` - DateTimeOffset to byte array
88+
* `DateTimeOffsetToStringConverter` - DateTimeOffset to string
89+
* `DateTimeToBinaryConverter` - DateTime to 64-bit value including DateTimeKind
90+
* `DateTimeToStringConverter` - DateTime to string
91+
* `DateTimeToTicksConverter` - DateTime to ticks
92+
* `EnumToNumberConverter` - Enum to underlying number
93+
* `EnumToStringConverter` - Enum to string
94+
* `GuidToBytesConverter` - Guid to byte array
95+
* `GuidToStringConverter` - Guid to string
96+
* `NumberToBytesConverter` - Any numerical value to byte array
97+
* `NumberToStringConverter` - Any numerical value to string
98+
* `StringToBytesConverter` - String to UTF8 bytes
99+
* `TimeSpanToStringConverter` - TimeSpan to string
100+
* `TimeSpanToTicksConverter` - TimeSpan to ticks
101+
102+
Notice that `EnumToStringConverter` is included in this list. This means that there is no need to specify the conversion explicitly, as shown above. Instead, just use the built-in converter:
103+
```C#
104+
var converter = new EnumToStringConverter<EquineBeast>();
105+
106+
modelBuilder
107+
.Entity<Rider>()
108+
.Property(e => e.Mount)
109+
.HasConversion(converter);
110+
```
111+
Note that all the built-in converters are stateless and so a single instance can be safely shared by multiple properties.
112+
113+
## Pre-defined conversions
114+
115+
For common conversions for which a built-in converter exists there is no need to specify the converter explicitly. Instead, just configure which provider type should be used and EF will automatically use the appropriate build-in converter. Enum to string conversions are used as an example above, but EF will actually do this automatically if the provider type is configured:
116+
```C#
117+
modelBuilder
118+
.Entity<Rider>()
119+
.Property(e => e.Mount)
120+
.HasConversion<string>();
121+
```
122+
The same thing can be achieved by explicitly specifying the column type. For example, if the entity type is defined like so:
123+
```C#
124+
public class Rider
125+
{
126+
public int Id { get; set; }
127+
128+
[Column(TypeName = "nvarchar(24)")]
129+
public EquineBeast Mount { get; set; }
130+
}
131+
```
132+
Then the enum values will be saved as strings in the database without any further configuration in OnModelCreating.
133+
134+
## Limitations
135+
136+
There are a few known current limitations of the value convertion system:
137+
* As noted above, `null` cannot be converted.
138+
* There is currently no way to spread a conversion of one property to multuple columns or vice-versa.
139+
* Use of value conversions may impact the ability of EF Core to translate expressions to SQL. A warning will be logged for such cases.
140+
Removal of these limitations is being considered for a future release.

entity-framework/toc.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#### [Alternate Keys](core/modeling/alternate-keys.md)
4545
#### [Inheritance](core/modeling/inheritance.md)
4646
#### [Backing Fields](core/modeling/backing-field.md)
47+
#### [Value Conversions](core/modeling/value-conversions.md)
4748
#### [Alternating models with same DbContext](core/modeling/dynamic-model.md)
4849
#### [Relational Database Modeling](core/modeling/relational/index.md)
4950
##### [Table Mapping](core/modeling/relational/tables.md)

0 commit comments

Comments
 (0)