Реализуем поддержку enum для Entity Framework Code First

В данный момент Entity Framework Code First поддерживает перечисления только в текущей бета версии (June CTP). Однако, эту возможность можно легко реализовать самостоятельно. Посмотрим на примере.

Предположим в исходном коде приложения определено следующее перечисление:

public enum CarBodyStyle : int
{
    Unknow = 0,
    Sedan = 1,
    Hatchback = 2,
    Coupe = 3

    .........
}

Теперь посмотрим на исходную Модель:

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

    public string Name { get; set; }

    public CarBodyStyle BodyStyle { get; set; }

    .........
}

BodyStyle не будет отражено в базе данных, поскольку Code First не умеет работать с enum. Для решения этой проблемы в Модель добавим вспомогательное свойство BodyStyleId типа int, которое и будет размещено в таблице. А при помощи методов get и set установим его связь с исходным перечислением.

Теперь постараемся максимально скрыть факт использования BodyStyleId. Для этого применим к нему атрибут [Column] чтобы задать имя колонки без окончания "Id". Кроме того, немного подстрахуемся и отметим свойство BodyStyle как [NotMapped]. Это необходимо для того, чтобы после выхода Entity Framework с поддержкой перечислений, не получить исключения, уведомляющего об изменении Модели.

В результате получится следующий вариант класса Car:

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

    public string Name { get; set; }

    [Column("BodyStyle")]
    public int BodyStyleId
    {
        get { return (int)this.BodyStyle; }
        set { this.BodyStyle = (CarBodyStyle)value; } 
    }

    [NotMapped]
    public CarBodyStyle BodyStyle { get; set; }
}

В исходном коде разрабатываемого приложения будем обращаться только к свойству BodyStyle. В дальнейшем, когда официально выйдет обновление Code First с поддержкой enum, можно будет просто отказаться от свойства BodyStyleId. Причем это произойдет незаметно для остальных частей приложения.

Комментарии (8) -

Ага, стандартный workaround. Есть только одна проблема - по enum'у нельзя делать запросы

Этот момент можно смягчить, например, используя спецификации. Тогда внутри одной из них можно "скрытно" обращаться к BodyStyleId.

Раз мы предполагаем, что используются спецификации, можно сделать BodyStyleId internal, чтобы снаружи был виден только enum. Хотя если модель и спецификации находятся в разных сборках, придется использоваться InternalVisibleTo (конечно, как временное решение до релиза полноценной поддержки enum).

В принципе можно, но мне лично не сильно нравится сама идея InternalVisibleTo.

Есть один очень полезный компонент, который предоставляет поддержку enum для EF

blogs.msdn.com/.../...framework-june-2011-ctp.aspx

Я про June CTP в самом начале и упомянул.

Сорри за невнимательность

Вместо internal наверное будет лучше добавить BrowsableAttribute
msdn.microsoft.com/.../....browsableattribute.aspx
Не знаю, есть уже поддержка enum или нет

Добавить комментарий