列挙体メンバーを文字列としてDBに保存

Entity Frameworkで列挙体をメンバーとして持つEntityをコードファーストにて、テーブルを作成すると、列挙体部分は整数(int)型となる。列挙体中の並びに変更が無ければ問題にならないのだが、DBに値を保存した後で列挙体の順番が変更されてしまうと齟齬が発生する。

列挙体への項目挿入などの変更が考えられる場合には、DB中に列挙体メンバー名を文字列化して保存した方が良いかもしれない。

このような値変換を行うには、DbContextから派生させたクラスで、OnModelCreatingをオーバーライドして、Entity中のプロパティについて値コンバーターを定義すればよい。

// Alert Level
public enum AlertLevel { Debug, Information, Warning, Error, Fatal }
// Message
public class AlertMessage {
    [Key]
    public int MessaegId { get; set; }
    public AlertLevel Level { get; set; }
    public string Message { get; set; } = null!;
    public DateTime LogDate { get; set; }
}
// DbContext
public class ConvTestCtx : DbContext {
    public DbSet<AlertMessage> Messages { get; set; } = null!;
		・・・
    protected override void OnModelCreating(ModelBuilder modelBuilder) {
        modelBuilder
            .Entity<AlertMessage>()
            .Property(e => e.Level)
            .HasConversion(
                v=>v.ToString(),    // Instance⇒DB
                v=>(AlertLevel)Enum.Parse(typeof(AlertLevel),v) // DB⇒Instance
            );
    }
}

これで、生成されるテーブル作成SQLは以下の通り。

CREATE TABLE [Messages] (
    [MessaegId] int NOT NULL IDENTITY,
    [Level] nvarchar(max) NOT NULL,
    [Message] nvarchar(max) NOT NULL,
    [LogDate] datetime2 NOT NULL,
    CONSTRAINT [PK_Messages] PRIMARY KEY ([MessaegId])
);

ご覧のとおり、Levelがnvarchar(max)となっている。実際に登録した結果は以下の通り。

MessaegId Level	       Message 	           LogDate
5	  Information  System has Started  2023/03/24 08:53:15
6	  Warning      Low Battery	   2023/03/24 08:53:17
7	  Debug	       Debug Message	   2023/03/24 08:53:18

てな感じで、双方向の型変換が可能。

takezou について

ソフトウェア開発会社(ITと言う言葉は大嫌い)で働く、元技術者。 未だに、社内システム位は作ってますが・・・ プログラミング言語はC#が好き。 好きなことだけ拾って投稿しているので、内容にはあまり期待しないでねw
カテゴリー: .NET, Entity Framework, 技術系 パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください