Подделка перечислений в Entity Framework 4.0

#c#-4.0 #entity-framework-4 #poco

#c #-4.0 #entity-framework-4 #poco

Вопрос:

Существует множество обходных путей для устранения отсутствующей поддержки перечислений в Entity Framework 4.0. Из всех них мне больше всего нравится этот:

http://blogs.msdn.com/b/alexj/archive/2009/06/05/tip-23-how-to-fake-enums-in-ef-4.aspx ?Индекс страницы= 2#комментарии

Этот обходной путь позволяет вам использовать перечисления в ваших запросах LINQ, что мне именно и нужно. Однако у меня возникла проблема с этим обходным путем. Я получаю для каждого сложного типа, который я использую, новый частично автоматически созданный класс.Поэтому код больше не компилируется, потому что у меня уже есть класс-оболочка с этим именем в том же пространстве имен, который преобразует между сохраненным целым числом в базе данных и перечислением в моих классах POCO. Если я сделаю свою оболочку частичным классом, код все равно не скомпилируется, поскольку теперь он содержит два свойства с одинаковым именем «Value». Единственная возможность — удалять свойство Value вручную каждый раз, когда я генерирую классы POCO, потому что модель БД изменилась (что на этапе разработки происходит очень часто).

Знаете ли вы, как предотвратить создание частичного класса из сложного свойства при каждом изменении модели EF?

Можете ли вы порекомендовать мне какие-либо другие обходные пути, поддерживающие перечисления в запросах LINQ?

Ответ №1:

Это обходное решение основано на том факте, что вы сами пишете свои классы POCO = автогенерации нет. Если вы хотите использовать его с автоматической генерацией, вы должны сильно модифицировать сам шаблон T4.

Другим обходным путем является перенос преобразования перечислений в пользовательские методы расширения.

 public static IQueryable<MyEntity> FilterByMyEnum(this IQueryable<MyEntity> query, MyEnum enumValue)
{
    int val = (int)enumValue;
    return query.Where(e => e.MyEnumValue == val);
}
  

Затем вы вызовете просто:

 var data = context.MyEntitites.FilterByMyEnum(MyEnum.SomeValue).ToList();
  

Ответ №2:

Я использую подход, основанный на том, который описан в вашей ссылке, без каких-либо изменений шаблонов T4. Содержимое моих классов-частичных оболочек выглядит следующим образом:

 public partial class PriorityWrapper
{
    public Priority EnumValue
    {
        get
        {
            return (Priority)Value;
        }
        set
        {
            Value = (int)value;
        }
    }

    public static implicit operator PriorityWrapper(Priority value)
    {
        return new PriorityWrapper { EnumValue = value };
    }

    public static implicit operator Priority(PriorityWrapper value)
    {
        if (value == null)
            return Priority.High;
        else
            return value.EnumValue;
    }
}
  

Я изменил только то, что вместо переменной обратного хранилища со значением enum я использую автоматически созданное свойство int typed Value. Следовательно, Value может быть автоматически реализованным свойством, а свойство EnumValue должно выполнять преобразование в методах getter и setter.

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

1. разве в этом не отсутствует определение Value атрибута?

2. @superjos Как я описал в тексте под кодом, в данном случае Value это автоматически сгенерированное int свойство, которое определено в автоматически сгенерированной части частичного класса (подход, основанный на модели). В любом случае, с тех пор в EF5 была добавлена надлежащая поддержка перечислений.

3. О, я понимаю. Мне пришлось перечитать это, чтобы заметить это. Спасибо за отзыв.