Как переписать выражения запросов для замены перечислений с помощью ints?
Вдохновленный желанием использовать перечисления в EF-запросах, я рассматриваю возможность добавления ExpressionVisitor в свои репозитории, которые будут принимать критерии входящих критериев/спецификаций и переписывать их для использования соответствующего сохраняемого свойства int.
Я последовательно использую следующий шаблон Value-suffix в моих (кодовых первых) объектах:
public class User : IEntity
{
public long ID { get; set; }
internal int MemberStatusValue { get; set; }
public MemberStatus MemberStatus
{
get { return (MemberStatus) MemberStatusValue; }
set { MemberStatusValue = (int) value; }
}
}
И сопоставьте это с базой данных, используя следующее:
internal class UserMapping : AbstractMappingProvider<User>
{
public override void DefineModel( DbModelBuilder modelBuilder )
{
// adds ToTable and other general mappings
base.DefineModel( modelBuilder );
Map.Property( e => e.MemberStatusValue ).HasColumnName( "MemberStatus" );
}
}
В моих репозиториях есть следующий метод:
public IQueryable<T> Query( Expression<Func<T, bool>> filter, params string[] children )
{
if( children == null || children.Length == 0 )
{
return Objects.Where( filter );
}
DbQuery<T> query = children.Aggregate<string, DbQuery<T>>( Objects, ( current, child ) => current.Include( child ) );
return filter != null ? query.Where( filter ) : query;
}
Я хотел бы добавить вызов метода внутри этого метода, чтобы переписать выражение фильтра, заменив все ссылки на свойство MemberStatus ссылками на MemberStatusValue.
Я предполагаю, что это будет решение с участием чего-то вроде увиденного в этом сообщении SO, но я точно не знаю, как перейти от идеи к реализации.
Если вы можете дать какой-либо совет о потенциальном влиянии производительности на добавление этой функции, это также будет оценено.
Ответы
Ответ 1
Я не уверен, что это совсем то, что вам нужно, но я нашел проще обрабатывать перечисления аналогичным, но немного другим способом. Разумеется, у меня есть два свойства, как и вы, но мое свойство int является общедоступным, и это то, что сохраняется в базе данных; Затем у меня есть другое общедоступное свойство "wrapper", которое получает/задает значение свойства int с помощью cast из/в нужный нумерованный тип, что фактически используется остальной частью приложения.
В результате мне не нужно возиться с моделью; EF понимает и сохраняет свойство int просто отлично, в то время как остальная часть приложения получает хорошие взаимодействия с типом перечисления. Единственное, что мне не нравится в моем подходе, это то, что я должен написать свои операторы LINQ с кучей кастингов для любого значения перечисления, которое я пытаюсь запросить, чтобы превратить его в int, чтобы он соответствовал фактическому состоянию. Это небольшая цена, и я хотел бы предложить вам это, потому что мне кажется, что вы используете строку для генерации вашего запроса, который дает все типы безопасности, Intellisense и т.д., Которые предоставляет LINQ.
Наконец, если вам интересно прочесть, как использовать новые функции enum в EF 5 (который доступен в бета-версии для загрузки сейчас, если вы хотите попробовать), проверьте это:
http://msdn.microsoft.com/en-us/hh859576