Подтвердить что ты не робот

Поддерживает ли PetaPoco перечисления?

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

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

public enum MyEnum
{
    Fred,
    Wilma
}

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

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

Convert.ChangeType( src, dstType, null );

Здесь src - "Fred" (a 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?

Обновление 23 февраля 2012

I представил патч некоторое время назад, но он еще не был взят. Если вы хотите использовать его, посмотрите на патч и объединитесь в свой собственный код или получите только код отсюда.

4b9b3361

Ответ 1

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

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

Ответ 2

Я использую 4.0.3, и PetaPoco автоматически конвертирует перечисления в целые числа и обратно. Тем не менее, я хотел преобразовать свои перечисления в строки и обратно. Воспользовавшись Steve Dunn EnumMapper и PetaPoco 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;
    }
}

Ответ 3

Если вы используете генерацию PetaPoco T4, и вы хотите перечислять в сгенерированном типе, вы можете использовать переопределение PropertyType в Database.tt:

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

Ответ 4

Я хочу сохранить значение перечисления вместо индекса (например, 1,2,4), вы можете найти функцию обновления в классе PetaPoco, потому что код "управляется" и т.д., когда вы добавляете его как nuget, он сохранит файл .cs в вашем проекте. Если бы мы имели переменную enum 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