2011-07-27 2 views
17

Я экспериментирую с PetaPoco, чтобы преобразовать таблицу в POCOs.Поддерживает ли PetaPoco перечисления?

В моей таблице у меня есть столбец с именем TheEnum. Значения в этом столбце являются строками, которые представляют собой следующее перечисление:

public enum MyEnum 
{ 
    Fred, 
    Wilma 
} 

PetaPoco задыхается, когда он пытается преобразовать строку «Fred» в значение MyEnum.

Он делает это в методе GetConverter, в строке:

Convert.ChangeType(src, dstType, null); 

Здесь src является "Фред" (а string), и dstType является typeof(MyEnum).

Исключение является InvalidCastException, говоря Invalid cast from 'System.String' to 'MyEnum'

ли я что-то отсутствует? Нужно ли мне сначала зарегистрироваться?

У меня вокруг проблемы, добавив следующее в метод GetConverter:

if (dstType.IsEnum && srcType == typeof(string)) 
{ 
    converter = delegate(object src) 
      { 
       return Enum.Parse(dstType, (string)src) ; 
      } ; 
} 

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

Итак, мой вопрос: мне нужно сделать что-нибудь особенное для регистрации моих перечислений с помощью PetaPoco?

Update 23 февраля 2012

submitted a patch Я некоторое время назад, но это не потянули в себе. Если вы хотите использовать его, посмотрите на патч и объединитесь в свой собственный код или получите только код from here.

+0

** Обновление 28 июня 2012 г. ** точный патч по-прежнему не применяется, но аналогичный код был добавлен в ветку [v5] (https://github.com/toptensoftware/PetaPoco/tree/v5). См. Также http://www.toptensoftware.com/Articles/137/Long-Time-No-Post-and-PetaPoco-v5 –

+0

Если вам это не сложно, отправьте патч на npoco. Я рекомендую вам переключиться на npoco, потому что он имеет более активную разработку и имеет все функции, которые есть у PetaPoco, и даже больше. – AuthorProxy

+0

** Обновление 9 сентября 2014 г. ** Ответ @iano является правильным для последней версии ** 5.0.2 **. –

ответ

5

Вы правы, обработка перечислений не встроена в PetaPoco, и обычно я предлагаю сделать именно то, что вы сделали.

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

+0

Спасибо, Брэд. Я добавлю список запросов и отправлю патч. –

+0

По состоянию на 27 декабря 2011 года исправление не применяется. Это будет приятное дополнение. – JCallico

+0

** Обновление 28 июня 2012 г. ** точный патч по-прежнему не применяется, но аналогичный код был добавлен в ветку [v5] (https://github.com/toptensoftware/PetaPoco/tree/v5). См. Также http://www.toptensoftware.com/Articles/137/Long-Time-No-Post-and-PetaPoco-v5 –

5

Я использую 4.0.3, и PetaPoco автоматически преобразует перечисления в целые числа и обратно. Тем не менее, я хотел преобразовать свои перечисления в строки и обратно. Воспользовавшись Steve Dunn's EnumMapper и PetaPoco's IMapper, я придумал это. Спасибо, парни.

Обратите внимание, что он не обрабатывает Nullable<TEnum> или нулевые значения в БД. Чтобы использовать его, установите PetaPoco.Database.Mapper = new MyMapper();

class MyMapper : PetaPoco.IMapper 
{ 
    static EnumMapper enumMapper = new EnumMapper(); 

    public void GetTableInfo(Type t, PetaPoco.TableInfo ti) 
    { 
     // pass-through implementation 
    } 

    public bool MapPropertyToColumn(System.Reflection.PropertyInfo pi, ref string columnName, ref bool resultColumn) 
    { 
     // pass-through implementation 
     return true; 
    } 

    public Func<object, object> GetFromDbConverter(System.Reflection.PropertyInfo pi, Type SourceType) 
    { 
     if (pi.PropertyType.IsEnum) 
     { 
      return dbObj => 
      { 
       string dbString = dbObj.ToString(); 
       return enumMapper.EnumFromString(pi.PropertyType, dbString); 
      }; 
     } 

     return null; 
    } 

    public Func<object, object> GetToDbConverter(Type SourceType) 
    { 
     if (SourceType.IsEnum) 
     { 
      return enumVal => 
      { 
       string enumString = enumMapper.StringFromEnum(enumVal); 
       return enumString; 
      }; 
     } 

     return null; 
    } 
} 
5

Если вы используете поколение T4 PetaPoco и вы хотите перечислений в вашем сгенерированного типа, вы можете использовать PropertyType переопределение в базе данных.тт:

tables["App"]["Type"].PropertyType = "Full.Namespace.To.AppType"; 
+0

Очень полезно. Благодаря! –

0

Я вы хотите сохранить значение перечисления вместо номера индекса (1,2,4), например, вы можете найти функцию обновления в классе PetaPoco, так как код «управляемой» и т.д. , добавив его как пакет nuget, он сохранит файл .cs в вашем проекте. Если бы переменной перечислимого типа Color = {красный, желтый, синий}

Вместо:

// Store the parameter in the command 
AddParam(cmd, pc.GetValue(poco), pc.PropertyInfo); 

изменение:

//enum? 
if (i.Value.PropertyInfo.PropertyType.IsEnum) 
{ 
     AddParam(cmd, i.Value.GetValue(poco).ToString(), i.Value.PropertyInfo); 
} 
else 
{ 
     // Store the parameter in the command 
     AddParam(cmd, i.Value.GetValue(poco), i.Value.PropertyInfo); 
} 

Он будет хранить "желтый" вместо 2

Смежные вопросы