值的轉換Value Conversions

注意

這項功能是在 EF 核心 2.1 中新功能。This feature is new in EF Core 2.1.

值轉換器可讓讀取或寫入資料庫時要轉換的屬性值。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.)

FundamentalsFundamentals

指定的值轉換器ModelClrTypeProviderClrTypeValue converters are specified in terms of a ModelClrType and a ProviderClrType. 模型類型是屬性的.NET 型別中的實體類型。The model type is the .NET type of the property in the entity type. 提供者類型為資料庫提供者所了解的.NET 類型。The provider type is the .NET type understood by the database provider. 例如,將列舉儲存成資料庫中的字串,模型型別是列舉的類型和提供者類型是StringFor 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.

轉換會使用兩個定義Func運算式樹狀架構: 從ModelClrTypeProviderClrType和從其他ProviderClrTypeModelClrTypeConversions 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.

設定的值轉換器Configuring a value converter

中的程式 DbContext OnModelCreating 屬性未定義值的轉換。Value conversions are defined on properties in the OnModelCreating of your DbContext. 例如,考慮列舉和實體類型定義為:For example, consider an enum and entity type defined as:

public class Rider
{
    public int Id { get; set; }
    public EquineBeast Mount { get; set; }
}

public enum EquineBeast
{
    Donkey,
    Mule,
    Horse,
    Unicorn
}

然後 OnModelCreating (例如,儲存為字串的列舉值中可以定義轉換「 Donkey","騾子",...)在資料庫中:Then conversions can be defined in OnModelCreating to store the enum values as strings (e.g. "Donkey", "Mule", ...) in the database:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<Rider>()
        .Property(e => e.Mount)
        .HasConversion(
            v => v.ToString(),
            v => (EquineBeast)Enum.Parse(typeof(EquineBeast), v));
}

注意

Anull值絕不會傳遞至值轉換器。A null value will never be passed to a value converter. 這會使您更輕鬆的轉換實作,並讓他們在可為 null 與不可為 null 的屬性之間會共用。This makes the implementation of conversions easier and allows them to be shared amongst nullable and non-nullable properties.

ValueConverter 類別The ValueConverter class

呼叫HasConversion如上所示將建立ValueConverter執行個體,並將其設定的屬性。Calling HasConversion as shown above will create a ValueConverter instance and set it on the property. ValueConverter改為明確建立。The ValueConverter can instead be created explicitly. 例如:For example:

var converter = new ValueConverter<EquineBeast, string>(
    v => v.ToString(),
    v => (EquineBeast)Enum.Parse(typeof(EquineBeast), v));

modelBuilder
    .Entity<Rider>()
    .Property(e => e.Mount)
    .HasConversion(converter);

當多個屬性使用相同的轉換時,這非常有用。This can be useful when multiple properties use the same conversion.

注意

目前沒有任何方法可以在一個位置指定特定類型的每個屬性都必須使用相同的值轉換器。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.

內建轉換程式Built-in converters

EF 核心隨附一組預先定義的ValueConverter中找到的類別Microsoft.EntityFrameworkCore.Storage.ValueConversion命名空間。EF Core ships with a set of pre-defined ValueConverter classes, found in the Microsoft.EntityFrameworkCore.Storage.ValueConversion namespace. 這些是:These are:

  • BoolToZeroOneConverter 為零,而另一個 BoolBoolToZeroOneConverter - Bool to zero and one
  • BoolToStringConverter -字串,例如"Y"和"N"BoolBoolToStringConverter - Bool to strings such as "Y" and "N"
  • BoolToTwoValuesConverter -任何兩個值 BoolBoolToTwoValuesConverter - Bool to any two values
  • BytesToStringConverter 以 Base64 編碼字串的位元組陣列BytesToStringConverter - Byte array to Base64-encoded string
  • CastingConverter -需要 Csharp 轉換的轉換CastingConverter - Conversions that require only a Csharp cast
  • CharToStringConverter -Char 為單一字元字串CharToStringConverter - Char to single character string
  • DateTimeOffsetToBinaryConverter -DateTimeOffset 二進位編碼的 64 位元值DateTimeOffsetToBinaryConverter - DateTimeOffset to binary-encoded 64-bit value
  • DateTimeOffsetToBytesConverter 為位元組陣列 DateTimeOffsetDateTimeOffsetToBytesConverter - DateTimeOffset to byte array
  • DateTimeOffsetToStringConverter -DateTimeOffset 字串DateTimeOffsetToStringConverter - DateTimeOffset to string
  • DateTimeToBinaryConverter -包括 DateTimeKind 的 64 位元值的日期時間DateTimeToBinaryConverter - DateTime to 64-bit value including DateTimeKind
  • DateTimeToStringConverter 日期時間字串DateTimeToStringConverter - DateTime to string
  • DateTimeToTicksConverter 日期時間以刻度為單位DateTimeToTicksConverter - DateTime to ticks
  • EnumToNumberConverter 列舉為基礎的數字EnumToNumberConverter - Enum to underlying number
  • EnumToStringConverter 列舉字串EnumToStringConverter - Enum to string
  • GuidToBytesConverter 的位元組陣列 Rights-guidGuidToBytesConverter - Guid to byte array
  • GuidToStringConverter Guid 字串GuidToStringConverter - Guid to string
  • NumberToBytesConverter 的位元組陣列任何數值NumberToBytesConverter - Any numerical value to byte array
  • NumberToStringConverter -任何數值字串NumberToStringConverter - Any numerical value to string
  • StringToBytesConverter -UTF8 位元組字串StringToBytesConverter - String to UTF8 bytes
  • TimeSpanToStringConverter -TimeSpan 字串TimeSpanToStringConverter - TimeSpan to string
  • TimeSpanToTicksConverter -要刻度的時間範圍TimeSpanToTicksConverter - TimeSpan to ticks

請注意,EnumToStringConverter包含在此清單。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:

var converter = new EnumToStringConverter<EquineBeast>();

modelBuilder
    .Entity<Rider>()
    .Property(e => e.Mount)
    .HasConversion(converter);

請注意,所有內建的轉換器是無狀態,因此單一執行個體可以安全地共用的多個屬性。Note that all the built-in converters are stateless and so a single instance can be safely shared by multiple properties.

預先定義的轉換Pre-defined conversions

一般轉換的內建的轉換器沒有需要明確指定轉換器。For common conversions for which a built-in converter exists there is no need to specify the converter explicitly. 相反地,只要設定應該使用哪一個提供者類型和 EF 會自動使用適當的組建中轉換子。Instead, just configure which provider type should be used and EF will automatically use the appropriate build-in converter. 列舉字串轉換,會使用上述項目,例如,但是 EF 會實際執行此作業會自動如果設定提供者類型:Enum to string conversions are used as an example above, but EF will actually do this automatically if the provider type is configured:

modelBuilder
    .Entity<Rider>()
    .Property(e => e.Mount)
    .HasConversion<string>();

達到相同的動作時,可以藉由明確指定資料行類型。The same thing can be achieved by explicitly specifying the column type. 例如,如果實體類型的定義也因此:For example, if the entity type is defined like so:

public class Rider
{
    public int Id { get; set; }

    [Column(TypeName = "nvarchar(24)")]
    public EquineBeast Mount { get; set; }
}

列舉值會儲存成不需任何進一步設定 OnModelCreating 在資料庫中的字串。Then the enum values will be saved as strings in the database without any further configuration in OnModelCreating.

限制Limitations

有幾個已知目前系統的限制值轉換:There are a few known current limitations of the value convertion system:

  • 如上所述,null無法轉換。As noted above, null cannot be converted.
  • 目前沒有任何方法可以散佈某個屬性轉換為多個資料行,反之亦然。There is currently no way to spread a conversion of one property to multiple columns or vice-versa.
  • 使用值的轉換可能會影響 EF 核心能夠將運算式轉譯為 SQL。Use of value conversions may impact the ability of EF Core to translate expressions to SQL. 這種情況下,將會記錄警告。A warning will be logged for such cases. 移除這些限制都被視為未來的版本。Removal of these limitations is being considered for a future release.