ツナ缶雑記

ぐうたらSEのブログです。主にマイクロソフト系技術を中心に扱います。

Entity Framework 6 DBファーストで数値型のカラムをEnumとして取り扱う方法

やりたいこと

Entity Frameworkのデータベースファーストを使用する場合、モデルクラスの各プロパティの型は、データベースの型によって勝手に決められます。「XXステータス」のように、取りうる値が決まっているケースでは、.NETアプリケーション内でできればEnumを使用したいところです。しかし、単純にモデルクラスを生成しただけでは、Enumを使うようにしてくれません。今回はEnumを使うように設定する方法を解説します。

環境

対象のテーブル

以下のようなテーブルを準備します。

CREATE TABLE [dbo].[Table] (
    [Id]     INT      NOT NULL,
    [Status] SMALLINT NOT NULL
);

とりあえずモデルクラスを生成する

Visual Studioで「ADO.NET Entity Data Model」を新たに作成します。そして上記のテーブルをモデルとして生成します。すると以下のようなモデルが生成されます。

f:id:masatsuna:20190702111934p:plain
Entity Framework 6のデザイナー

「Status」のプロパティを参照すると、型が「Int16」にマッピングされているのがわかります。次にこの「Status」をEnumで取り扱えるようにします。

Enumを使えるようにする

まずedmxファイルを開いて、対象のプロパティを右クリックします。そして「Enumに変換」を押下します。

f:id:masatsuna:20190702112904p:plain
Enumに変換

新たに列挙型を作成する場合

新たに列挙型を作成する場合は、「列挙型の追加」画面で追加する列挙型の名前、基になる型、値のリストを設定して「OK」ボタンを押下します。

f:id:masatsuna:20190702113537p:plain
Enumの設定

すると、設定した通りのEnumが新たに生成されます。生成する先は、以下の通りです。

f:id:masatsuna:20190702113927p:plain
Enumの生成後

なお設定したのにEnumが生成されいていない場合は、再度ビルドするか、edmxを右クリックして「カスタムツールの実行」を選択してください。

f:id:masatsuna:20190702114139p:plain
カスタムツールの実行

生成されたEnumは以下のようになります。

//------------------------------------------------------------------------------
// <auto-generated>
//     このコードはテンプレートから生成されました。
//
//     このファイルを手動で変更すると、アプリケーションで予期しない動作が発生する可能性があります。
//     このファイルに対する手動の変更は、コードが再生成されると上書きされます。
// </auto-generated>
//------------------------------------------------------------------------------

namespace EF_Enum.DataAccess
{
    using System;
    
    public enum Status : short
    {
        Default = 0,
        Executing = 1,
        Done = 2
    }
}

既存の列挙型を使用する場合

既に列挙型の定義ができている場合は、その型をモデルクラスで使用することもできます。以下のEnumをEntity Frameworkのモデルクラスから使用してみます。

namespace EF_Enum
{
    public enum Status : short
    {
        Default = 0,
        Executing = 1,
        Done = 2
    }
}

前述の手順同様、「列挙型の追加」画面まで進みます。「名前」に任意の名前を入れて、「外部の型の参照」に存在するEnumの型名を設定します。型名は名前空間を含む完全修飾名で指定することに注意してください。

f:id:masatsuna:20190702120649p:plain
既存のEnumを利用する場合

モデルクラスの再生成を行うと、モデルクラスが以下のように書き換わります。

//------------------------------------------------------------------------------
// <auto-generated>
//     このコードはテンプレートから生成されました。
//
//     このファイルを手動で変更すると、アプリケーションで予期しない動作が発生する可能性があります。
//     このファイルに対する手動の変更は、コードが再生成されると上書きされます。
// </auto-generated>
//------------------------------------------------------------------------------

namespace EF_Enum.DataAccess
{
    using System;
    using System.Collections.Generic;
    
    public partial class Table
    {
        public int Id { get; set; }
        public EF_Enum.Status Status { get; set; }
    }
}

確かに、指定したEnumが使われるようになっていることがわかります。

何が嬉しいのか

特にWhere句を組み立てる際、以下のように型を利用した実装ができるようになります。実装から「妙な数字」が消え去るので、可読性が大きく向上します。

using (EFEnumTestDbContext context = new EFEnumTestDbContext())
{
    var count = context.Tables.Where(r => r.Status == Status.Done).Count();
}