EntityFrameworkCoreのValueConverterを試す
ASP.NET Core の All やら App のパッケージを利用すると漏れなく付いてくるという噂の EntityFrameworkCore ですが、2.1からデータベースとやりとりする型とマッピングされるエンティティモデル上のプロパティの型とを変換する ValueConverter
が追加されていたようです。とても欲しかった機能なのですが気付くのが遅れました。この値変換機能を試してみた結果です。
試した環境
- macOS 10.13.6
- .NET Core 2.2.1 (2.2.103)
- EntityFrameworkCore 2.2.1
組み込みのValueConverterを利用する
定義されている ValueConverter
EntityFrameworkCore にはいくつかの良く利用しそうな ValueConverter が実装されています。以下はドキュメントを表にまとめたものです。全て Microsoft.EntityFrameworkCore.Storage.ValueConversion
名前空間にいます。
クラス名 | モデルの型 | DBの型 | 説明 |
---|---|---|---|
BoolToZeroOneConverter |
bool |
int short など |
boolを0または1に変換。変換先はC#組み込みの数値型(intやshort、doubleなど)が指定出来る。 |
BoolToStringConverter |
bool |
string |
boolを指定した文字に変換。 |
BoolToTwoValuesConverter |
bool |
any |
boolを指定した値に変換。 |
BytesToStringConverter |
byte[] |
string |
バイト配列をBase64形式の文字列に変換。 |
CastingConverter |
any |
any |
ただ型をキャストするだけ。 |
CharToStringConverter |
char |
string |
charを1文字のstringに変換。 |
DateTimeOffsetToBinaryConverter |
DateTimeOffset |
long |
日時をlongのバイナリ値に変換。 |
DateTimeOffsetToBytesConverter |
DateTimeOffset |
byte[] |
日時をバイト配列に変換。 |
DateTimeOffsetToStringConverter |
DateTimeOffset |
string |
日時を文字列に変換。 |
DateTimeToBinaryConverter |
DateTime |
long |
DateTimeKindも含んだ日時をlongのバイナリ値に変換。 |
DateTimeToStringConverter |
DateTime |
string |
日時を文字列に変換。 |
DateTimeToTicksConverter |
DateTime |
long |
日時をTicksに変換。タイムスタンプでは無い。 |
EnumToNumberConverter |
Enum |
int short など |
Enumを値の数値に変換。変換先はC#組み込みの数値型(intやshort、doubleなど)が指定出来る。 |
EnumToStringConverter |
Enum |
string |
Enumを名前の文字列に変換。 |
GuidToBytesConverter |
Guid |
byte[] |
Guidをバイト配列に変換。 |
GuidToStringConverter |
Guid |
string |
Guidを文字列( "8-4-4-4-12" 形式)に変換。 |
NumberToBytesConverter |
int short など |
byte[] |
数値をバイト配列に変換。変換元はC#組み込みの数値型(intやshort、doubleなど)が指定出来る。 |
NumberToStringConverter |
int short など |
string |
数値を文字列に変換。 |
StringToBytesConverter |
string |
byte[] |
文字列をUTF-8形式のバイト配列に変換。 |
TimeSpanToStringConverter |
TimeSpan |
string |
TimeSpanを文字列に変換。 |
TimeSpanToTicksConverter |
TimeSpan |
long |
TimeSpanをTicksに変換。 |
ValueConverterを使用する
ValueConverterは今のところ対象のプロパティに対して Fluent API で指定することで使用できます。 Attribute を使用して設定することはできません。また特定の型に対して一括で指定するような方法もありません。。
Fluent API で ValueConverter を使用するには HasConvention
メソッドを使用します。注意する点として、 HasConvention
メソッドに渡すのは ValueConverter の型ではなくインスタンス化したオブジェクトを渡す事です。筆者はここを間違えてしばらく悩みました。。。
// Guidを xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 形式の文字列に変換 var guidToStringConverter = new GuidToStringConverter(); // Enumを対応する数値型に変換 var enumToNumberConverter = new EnumToNumberConverter<DayOfWeek, int>(); // boolを文字列(0/1)に変換 var boolToStringConverter = new BoolToStringConverter("0", "1"); modelBuilder.Entity<SampleEntity>(builder => { builder .ToTable("sample") .HasKey(e => e.Id); builder .Property(e => e.Id) .HasColumnType("CHAR(36)") .IsUnicode(false) .HasConversion(guidToStringConverter); builder .Property(e => e.DayOfWeek) .HasColumnType("CHAR(1)") .IsUnicode(false) .HasConversion(enumToNumberConverter); builder .Property(e => e.Deleted) .HasColumnType("CHAR(1)") .IsUnicode(false) .HasConversion(boolToStringConverter); });