2015-03-18 7 views
0

В настоящее время я использую Entity Framework для проекта, и один из моих классов имеет Enum, представляющий некоторые значения.Как перехватить операции EF?

До сих пор EF сохранял Enums как числа в базе данных, но я хотел сохранить их как их фактические имена строк. Например, Enum NY сохраняется как 1, а не «NY».

Я уже видел некоторые способы сделать эту работу, например, иметь свойство string со скрытым полем Enum private, но я хотел знать, есть ли способ, которым я могу просто перехватить EF, когда он выполняет операции CRUD, а затем Я могу изменить Enum на String в классе Data Context.

+0

Я бы сказал, что это не проблема, которую стоит решить. Суррогатные ключи превосходят как производительность, так и ремонтопригодность. Знаете ли вы, что в 1960-х годах сократились государственные сокращения? Кроме того, что, если добавить дополнительные города? – TheCatWhisperer

+0

Я думаю, что это много читаемо, чтобы иметь имена в базе данных, чем некоторые случайные числа, зависящие от версии моего кода. – mFeinstein

+1

Чтобы узнать читаемость в БД: 1. Виды 2. Вот почему у вас есть таблица поиска Что касается кода, вот почему вы используете перечисление в первую очередь. И, к сожалению, если вы используете EF, приложение уже напрямую связано с вашей БД. – TheCatWhisperer

ответ

0

Нет, вы не можете сделать это напрямую: когда вы сопоставляете свой класс с свойством Enum, это свойство сопоставляется с базой данных int, и вы не можете изменить это каким-либо образом. Я имею в виду, что, как вы не можете изменить модель, нет никакого способа, чтобы перехватить и преобразовать значение Enum свойства в строку, так как модель упорно хочет int.

Тем не менее, есть несколько способов, чтобы сделать его работу:

  • , имеющие свойство строки для ключа и [NotMapped]Enum свойство, которое обновляет этот ключ. СМ. ЗАМЕЧАНИЕ. Но ключ должен быть общедоступным и, таким образом, доступен через код приложения.
  • , используя класс, есть только свойство перечислимого и используются в домене приложения, а другой класс, который используется для вашей модели EF, и отображать значения, например, с помощью ValueInjecter или Automapper

Обычно я беру первый путь и использую атрибут, который позволяет мне определить строковый ключ для каждого значения Enum, поэтому вы можете повторно использовать этот шаблон во всех случаях, когда это необходимо.

Примечание: эта часть ответа не так: вы можете отображать любое имущественное regardles модификатора (public, protected, private, internal ...). Соглашения EF включают только свойства public, и нет никаких аннотаций данных, которые могут преодолеть это ограничение. Но вы можете использовать его с Fluent API. Однако, поскольку свойство является приватным, вы не можете получить к нему доступ напрямую, используя Fluent API. Есть несколько решений, чтобы сделать это описано здесь: Code First Data Annotations on non-public properties

Если вы будете следовать этому пути, вы можете иметь класс, как это:

public class MyEntity 
{ 
    // ... 

    [NotMapped] 
    public EnumType Value 
    { 
    get { /* return KeyForEnum converted to EnumType value */ } 
    set { /* set KeyForEnum value from the received EnumType value*/} 
    } 

    // Use some mechanism to map this private property 
    private string KeyForEnum { get; set; } 

    // ... 
} 

Как вы можете видеть, если вы используете класс, как это, в приложении объект будет иметь свойство EnumType, но в базе данных это будет строка.

Одна из уловок, чтобы иметь возможность сопоставить его с помощью Fluent API заключается в следующем:

1) Добавить статическое свойство, которое возвращает выражение, способное выбрать свойство из объекта этого класса, т.е.

public static readonly Expression<Func<MyEntity,string>> KeyForEnumExpression 
    = me => me.KeyForEnum; 

2) Используйте его в беглом API, чтобы получить свойство отображается, например, так:

modelBuilder 
    .Entity() 
    .Property(MyEntity.KeyForEnumExpression) 

ПОСЛЕДНЕГО ПРИМЕЧАНИЕ: Это будет изменить класс POCO путем добавления статического свойства только для чтения. Вы можете использовать Reflection вместо этого, чтобы создать выражение для доступа к частной собственности, как вы можете здесь: EF 4.1 Code First, ¿map private members?. Это на испанском, но вы можете посмотреть прямо на код