воскресенье, 8 мая 2016 г.

Entity Framework Code-Frist. Маппинг enum свойств в nvarchar

По умолчанию Entity Framework Code-First маппит enum свойства к sql колонкам типа integer. Мапинг в обе стороны проходит без проблем, и вообще всё работает отлично. Однако, может возникнуть необходимость изменить тип sql колонки на nvarchar. Стандартными средствами Code-First подход настраивать типы колонок не позволяет. Тем не менее можно провернуть следующие ухищрения.
Пусть у нас есть тип AuditRecord, который маппится в БД. В нём находится поле ActionType типа AuditActionType (enum). Таким образом, получаем следующее:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public class AuditRecord
{
    [Required]
    [Column("ActionType")]
    [MaxLength(32)]
    public string ActionTypeString
    {
        get { return ActionType.ToString(); }
        private set { ActionType = EnumExtensions.ParseEnum<AuditActionType>(value); }
    }
 
    [NotMapped]
    public AuditActionType ActionType { get; set; }
}

Здесь я использовал extension-метод ParseEnum, который выглядит следующим образом:

1
2
3
4
5
6
7
public class EnumExtensions
{
    public static T ParseEnum<T>(String text)
    {
        return (T)Enum.Parse(typeof(T), text, true);
    }
}
Сеттер свойства ActionTypeString сделан приватным, чтобы предотвратить присвоения произвольных строк извне.
Основные минусы такого подхода:
  1. Работа со строковыми полями на больших объёмах данных в общем случае в БД медленнее, чем с integer.
  2. При фильтрации сущностей по данному полю для получения эффективного запроса в БД необходимо писать подобную лапшу:

context.AuditRecords.Where(ar => ar.ActionTypeString == AuditActionType.SomeAction.ToString());
Последнюю проблему можно решить изоляцией логики фильтрации на уровне репозиториев, чтобы знания об особенностях реализации не расползались за уровень DAL.

Комментариев нет:

Отправить комментарий