orm - ¿PetaPoco maneja las enumeraciones?
(4)
Estoy experimentando con PetaPoco para convertir una tabla en POCOs.
En mi tabla, tengo una columna llamada TheEnum
. Los valores en esta columna son cadenas que representan la siguiente enumeración:
public enum MyEnum
{
Fred,
Wilma
}
PetaPoco se ahoga cuando intenta convertir la cadena "Fred" en un valor de MyEnum
.
Lo hace en el método GetConverter
, en la línea:
Convert.ChangeType( src, dstType, null );
Aquí, src
es "Fred" (una string
), y dstType
es typeof(MyEnum)
.
La excepción es una excepción InvalidCastException
, que dice Invalid cast from ''System.String'' to ''MyEnum''
¿Me estoy perdiendo de algo? ¿Hay algo que necesito para registrarme primero?
GetConverter
el problema agregando lo siguiente al método GetConverter
:
if (dstType.IsEnum && srcType == typeof(string))
{
converter = delegate( object src )
{
return Enum.Parse( dstType, (string)src ) ;
} ;
}
Obviamente, no quiero ejecutar este delegado en cada fila ya que esto ralentizará enormemente las cosas. Podría registrar esta enumeración y sus valores en un diccionario para acelerar las cosas, pero me parece que es probable que algo como esto ya esté en el producto.
Entonces, mi pregunta es, ¿necesito hacer algo especial para registrar mis enums con PetaPoco?
Actualización 23 de febrero de 2012
He enviado un parche hace un tiempo, pero aún no se ha introducido. Si desea usarlo, mire el parche y fusione su propio código, o simplemente obtenga el código aquí .
Estoy usando 4.0.3 y PetaPoco convierte automáticamente enums a enteros y viceversa. Sin embargo, quería convertir mis enumeraciones a cadenas y volver. Aprovechando el EnumMapper de Steve Dunn y el IMapper de IMapper
, se me ocurrió esto. Gracias chicos.
Tenga en cuenta que no controla Nullable<TEnum>
o valores nulos en la base de datos. Para usarlo, configure 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;
}
}
Si desea almacenar el valor de la enumeración en lugar del número de índice (1,2,4 por ejemplo), puede ubicar la función de actualización en la clase PetaPoco porque el código es "administrado", etc., cuando lo agrega como un paquete nuget. almacenará el archivo .cs a su proyecto. Si tuviéramos la variable de enumeración Color = {rojo, amarillo, azul}
En lugar de:
// Store the parameter in the command
AddParam(cmd, pc.GetValue(poco), pc.PropertyInfo);
cambiar a:
//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);
}
Se almacenaría "amarillo" en lugar de 2.
Si está utilizando la generación T4 de PetaPoco y desea enumeraciones en su tipo generado, puede usar la anulación de PropertyType en Database.tt:
tables["App"]["Type"].PropertyType = "Full.Namespace.To.AppType";
Tienes razón, manejar enums no está integrado en PetaPoco y, por lo general, solo sugiero que hagas exactamente lo que has hecho.
Tenga en cuenta que esto no ralentizará las cosas para las solicitudes que no utilizan el tipo de enumeración. PetaPoco genera código para mapear las respuestas a pocos, por lo que solo se llamará al delegado cuando sea realmente necesario. En otras palabras, GetConverter solo se llamará la primera vez que se use un tipo de poco particular, y solo se llamará al delegado cuando una enumeración necesite conversión. No estoy seguro de la velocidad de Enum.Parse, pero sí, podría guardarlo en un diccionario si es demasiado lento.