Entity Framework允许使用不同的转换器,在保存和读取数据字段时将存储格式转换为目标对象。使用值转换器可以免去手动变更字段类型,自动实现数据存取的格式转换,为EF的使用带来很大方便。
值转换器允许在读取或写入数据库时转换属性值。 此转换可以从一个值转换为同一类型的另一个值 (例如,将字符串) 或从一种类型的值加密为另一种类型的值 (例如,在数据库中将枚举值与字符串相互转换。 )
Entity framework值转换器概述
值转换器以和的形式指定 ModelClrType
ProviderClrType
。 模型类型是实体类型中的属性的 .NET 类型。 提供程序类型是数据库提供程序理解的 .NET 类型。 例如,若要将枚举作为字符串保存在数据库中,模型类型是枚举的类型,而提供程序类型为 String
。 这两种类型可以相同。
使用两个 Func
表达式树来定义转换:一个从 ModelClrType
到 ProviderClrType
,另一个由 ProviderClrType
到 ModelClrType
。 使用表达式树,以便可以将它们编译到数据库访问委托中以便进行有效的转换。 对于复杂转换,表达式树可能包含对转换方法的简单调用。
为值转换配置的属性可能还需要指定 ValueComparer<T> 。 有关详细信息,请参阅下面的示例和 值 比较器文档。
相关概念
值转换器的使用方法
值转换在中进行配置 DbContext.OnModelCreating 。 在配置 OnModelCreating 中配置,为在数据库中存储枚举值(如 “Donkey”、”Mule” 等),只需提供一个将从转换 ModelClrType
为的函数 ProviderClrType
,另一个函数用于相反转换。
public class Rider
{
public int Id { get; set; }
public EquineBeast Mount { get; set; }
}
public enum EquineBeast
{
Donkey,
Mule,
Horse,
Unicorn
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Rider>()
.Property(e => e.Mount)
.HasConversion(
v => v.ToString(),
v => (EquineBeast)Enum.Parse(typeof(EquineBeast), v));
}
上面的示例中,还可以通过显式指定数据库列类型来实现相同的目的。 例如,如果定义了实体类型,如下所示:
public class Rider2
{
public int Id { get; set; }
[Column(TypeName = "nvarchar(24)")]
public EquineBeast Mount { get; set; }
}
null
值绝不会传递到值转换器。 数据库列中的 null 在实体实例中始终为 null,反之亦然。 这使得转换的实现变得更简单,并使其能够在可以为 null 和不可为 null 的属性之间共享。
Entity Framework内置值转换器
如上所述,EF Core 附带一组预定义的 ValueConverter<TModel,TProvider> 类,这些类位于 Microsoft.EntityFrameworkCore.Storage.ValueConversion 命名空间中。 在许多情况下,EF 会基于模型中的属性类型和数据库中所请求的类型选择适当的内置转换器,如上面的枚举所示。 例如, .HasConversion<int>()
对 bool
属性使用会导致 EF Core 将布尔值转换为数字零和一个值。此功能与创建内置的实例 BoolToZeroOneConverter<TProvider> 并显式设置它的功能相同。
所以对于内置转换器,都将会默认执行而不需要手动配置。
EF的内置转换器
下表汇总了从模型/属性类型到数据库提供程序类型的常用预定义转换。 在表中 any_numeric_type
,是指 int
、、、 short
long
byte
、 uint
、 ushort
ulong
sbyte
char
decimal
float
double
、、、、、或中的一个。
模型/属性类型 | 提供程序/数据库类型 | 转换 | 使用情况 |
---|---|---|---|
bool | any_numeric_type | False/true 到0/1 | .HasConversion<any_numeric_type>() |
any_numeric_type | 对于任意两个数值为 False/true | 使用 BoolToTwoValuesConverter<TProvider> | |
字符串 | False/true 到 “Y”/”N” | .HasConversion<string>() | |
字符串 | 对于任意两个字符串为 False/true | 使用 BoolToStringConverter | |
any_numeric_type | bool | 0/1 到 false/true | .HasConversion<bool>() |
any_numeric_type | 简单强制转换 | .HasConversion<any_numeric_type>() | |
字符串 | 字符串形式的数字 | .HasConversion<string>() | |
枚举 | any_numeric_type | 枚举的数值 | .HasConversion<any_numeric_type>() |
字符串 | 枚举值的字符串表示形式 | .HasConversion<string>() | |
字符串 | bool | 将字符串分析为布尔型 | .HasConversion<bool>() |
any_numeric_type | 将字符串分析为给定的数值类型 | .HasConversion<any_numeric_type>() | |
char | 字符串的第一个字符 | .HasConversion<char>() | |
DateTime | 将字符串分析为日期时间 | .HasConversion<DateTime>() | |
DateTimeOffset | 将字符串分析为 DateTimeOffset | .HasConversion<DateTimeOffset>() | |
TimeSpan | 将字符串分析为 TimeSpan | .HasConversion<TimeSpan>() | |
Guid | 将字符串分析为 Guid | .HasConversion<Guid>() | |
byte[] | UTF8 字节形式的字符串 | .HasConversion<byte[]>() | |
char | string | 单个字符串 | .HasConversion<string>() |
DateTime | long | 编码日期/时间保留日期时间类型 | .HasConversion<long>() |
long | Ticks | 使用 DateTimeToTicksConverter | |
字符串 | 固定区域性日期/时间字符串 | .HasConversion<string>() | |
DateTimeOffset | long | 带偏移量的编码日期/时间 | .HasConversion<long>() |
字符串 | 具有偏移量的固定区域性日期/时间字符串 | .HasConversion<string>() | |
TimeSpan | long | Ticks | .HasConversion<long>() |
字符串 | 固定区域性时间跨度字符串 | .HasConversion<string>() | |
URI | string | 字符串形式的 URI | .HasConversion<string>() |
PhysicalAddress | 字符串 | 字符串形式的地址 | .HasConversion<string>() |
byte[] | 大字节序网络顺序中的字节数 | .HasConversion<byte[]>() | |
IPAddress | 字符串 | 字符串形式的地址 | .HasConversion<string>() |
byte[] | 大字节序网络顺序中的字节数 | .HasConversion<byte[]>() | |
Guid | 字符串 | 采用 “dddddddd-dddd-dddd-dddd-dddddddddddd” 格式的 GUID | .HasConversion<string>() |
byte[] | .NET 二进制序列化顺序中的字节数 | .HasConversion<byte[]>() |
请注意,这些转换假定值的格式适用于转换。 例如,如果字符串值无法分析为数字,将字符串转换为数字将会失败。

公众号近期文章
0 Responses to “EnityFromework 字段转换值转换器的使用”