值的轉換Value Conversions

注意

這項功能是在 EF Core 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

在屬性上定義的值轉換OnModelCreating的程式DbContextValue 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 (for example, "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 Core 隨附一組預先定義的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 -Bool,例如"Y"和"n 名"的字串BoolToStringConverter - 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 -需要的轉換型別轉換CastingConverter - Conversions that require only a type cast
  • CharToStringConverter -Char 單一字元字串CharToStringConverter - Char to single character string
  • DateTimeOffsetToBinaryConverter -二進位編碼的 64 位元值 DateTimeOffsetDateTimeOffsetToBinaryConverter - DateTimeOffset to binary-encoded 64-bit value
  • DateTimeOffsetToBytesConverter 為位元組陣列 DateTimeOffsetDateTimeOffsetToBytesConverter - DateTimeOffset to byte array
  • DateTimeOffsetToStringConverter -字串 DateTimeOffsetDateTimeOffsetToStringConverter - 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 -Guid,以位元組陣列GuidToBytesConverter - Guid to byte array
  • GuidToStringConverter -字串 GuidGuidToStringConverter - 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 built-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; }
}

列舉值將會儲存為字串,而不需要任何進一步的設定,在資料庫中則OnModelCreatingThen 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 conversion 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 Core 能夠將運算式轉譯為 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.