Iniciar sesión
Registrarse
He olvidado mi contraseña
01 FEB 2012
Vistas de la Entrada 15 Vistas de la Entrada 5
Sin categoría
ORAPOCO: V2.0

Introducción

Bueno, como habréis podido notar ando creando un ORM “ligero” para trabajar contra Oracle (Serie ORAPOCO).

Bien, en la segunda actualización, tanto @Eiximenis como @Juanma, me indicaban algo que las clases POCO no debía implementar ninguna clase Base, algo que a mi tampoco me convencía haberlo agregado.

Además de ello Eduard comentaba la posibilidad de hacer configuración de los Mapeos, para evitar hacer uso de Atributos en las clases POCO y que están sean completamente POCO. El tema de los mapeos es parecido a lo que se ve en FluentNhibernate.

Por otro lado @_PedroHurtado, me comentaba que era posible hacer Sql Injection, y me propuso que modificara los parámetros String por Expression.

Bueno por estos motivos nace está nueva versión de ORAPOCO.

Cambios

Modificación de la Plantilla T4

He modificado la plantilla T4, de tal forma que va a generar objetos POCO, sin ningún tipo de atributo:

Objeto POCO:

1: public class BL_BLOQUEO_PANTALLA


2: {


3: public System.Int32 BLPA_ID {get;set;}


4: public System.String BLPA_PANTALLA {get;set;}


5: public System.String BLPA_FECHA {get;set;}


6: public System.String BLPA_HORA {get;set;}


7: public System.String BLPA_USUARIO {get;set;}


8: }


Del mismo modo se van a generar unas nuevas clases, que serán los Mapeadores por defecto:

1: public class BL_BLOQUEO_PANTALLAMapper : GenericMapper<BL_BLOQUEO_PANTALLA>


2: {


3: public Type GetMappedType()


4: {


5: return typeof(BL_BLOQUEO_PANTALLA);


6: }


7: public BL_BLOQUEO_PANTALLAMapper() : base()


8: {


9: AddColumnMapping(x=> x.BLPA_ID);


10: SetPrimaryKeyField(x => x.BLPA_ID);


11: AddColumnMapping(x=> x.BLPA_PANTALLA);


12: SetNullable(x=> x.BLPA_PANTALLA);


13: AddColumnMapping(x=> x.BLPA_FECHA);


14: SetNullable(x=> x.BLPA_FECHA);


15: AddColumnMapping(x=> x.BLPA_HORA);


16: SetNullable(x=> x.BLPA_HORA);


17: AddColumnMapping(x=> x.BLPA_USUARIO);


18: SetNullable(x=> x.BLPA_USUARIO);


19: }


20: }


Creación de los Objetos OracleColumnInfo,Mapper, IGenericMapper<T> y GenericMapper<T>

Para facilitar el mapeo de datos, he creado las siguientes clases e interfaz:

Clase OraceColumnInfo para representar la información relativa a cada columna de los objetos POCO.

1: public class OracleColumnInfo


2: {


3: public OracleColumnInfo()


4: {


5: IsPk = false;


6: Nullable = false;


7: }


8: public bool IsPk { get; set; }


9: public string ColumnName { get; set; }


10: public bool Nullable { get; set; }


11: public string DefaultValue { get; set; }


12: public string SequenceName { get; set; }


13: }


La Interfaz IGenericMapper<T>:

1: public interface IGenericMapper<T>


2: {


3: IGenericMapper<T> SetPrimaryKeyField(Expression<Func<T, object>> property);


4: IGenericMapper<T> AddColumnMapping(Expression<Func<T, object>> property);


5: IGenericMapper<T> SetNullable(Expression<Func<T, object>> property);


6: IGenericMapper<T> SetDefaultValue(Expression<Func<T, object>> property, string DefaultValue);


7: IGenericMapper<T> SetSequence(Expression<Func<T, object>> property, string SequenceName);


8: }


La clase Mapper: Va a servir para representar el conjunto de columnas de un objeto POCO.

La clase: GenericMapper<T>, va a extender a Mapper e implementar a IGenericMapper:

1: public class GenericMapper<T> : Mapper,IGenericMapper<T>


2: {


3: public GenericMapper()


4: {


5: Columns = new List<OracleColumnInfo>();


6: }


7: 


8: public IGenericMapper<T> AddColumnMapping(Expression<Func<T, object>> property)


9: {


10: PropertyInfo propertyInfo = GetProperty(property);


11: return this;


12: }


13:


14: public IGenericMapper<T> SetPrimaryKeyField(Expression<Func<T, object>> property)


15: {


16: PropertyInfo propertyInfo = GetProperty(property);


17: AddColumn(propertyInfo);


18: Columns.Where(col => col.ColumnName.Equals(propertyInfo.Name)).FirstOrDefault().IsPk = true;


19: return this;


20: }


21:


22: public IGenericMapper<T> SetNullable(Expression<Func<T, object>> property)


23: {


24: PropertyInfo propertyInfo = GetProperty(property);


25: AddColumn(propertyInfo);


26: Columns.Where(col => col.ColumnName.Equals(propertyInfo.Name)).FirstOrDefault().Nullable = true;


27: return this;


28: }


29: public IGenericMapper<T> SetDefaultValue(Expression<Func<T, object>> property, string DefaultValue)


30: {


31: PropertyInfo propertyInfo = GetProperty(property);


32: AddColumn(propertyInfo);


33: Columns.Where(col => col.ColumnName.Equals(propertyInfo.Name)).FirstOrDefault().DefaultValue = DefaultValue;


34: return this;


35: }


36: 


37: private void AddColumn(PropertyInfo propertyInfo)


38: {


39: var column = Columns.Where(col => col.ColumnName.Equals(propertyInfo.Name)).FirstOrDefault();


40: if (column == null)


41: Columns.Add(new OracleColumnInfo { ColumnName = propertyInfo.Name });


42: }


43: private static PropertyInfo GetProperty(Expression<Func<T, object>> property)


44: {


45: PropertyInfo propertyInfo = null;


46: if (property.Body is MemberExpression)


47: {


48: propertyInfo = (property.Body as MemberExpression).Member as PropertyInfo;


49: }


50: else


51: {


52: propertyInfo = (((UnaryExpression)property.Body).Operand as MemberExpression).Member as PropertyInfo;


53: }


54: 


55: return propertyInfo;


56: }


57:


58: public IGenericMapper<T> SetSequence(Expression<Func<T, object>> property, string SequenceName)


59: {


60: PropertyInfo propertyInfo = GetProperty(property);


61: AddColumn(propertyInfo);


62: Columns.Where(col => col.ColumnName.Equals(propertyInfo.Name)).FirstOrDefault().SequenceName = SequenceName;


63: return this;


64: }


65:


66: }


Creación de ConfigureMapping y AutoConfigureMapping

Ambos métodos van  a servir para configurar los Mapeos, y serán invocados de forma Manual.

AutoConfigureMapping, va a registrar todas aquellas clases que Implementen AutoConfigureMapping dentro del Assembly en el que nos encontremos.

Código:

Primer Ejemplo: Como crear y registrar un nuevo Mapeo:

1: db.ConfigureMapping<SAMPLE>(new GenericMapper<SAMPLE>().


2: SetPrimaryKeyField(x => x.ID).


3: AddColumnMapping(x => x.NOMBRE).


4: SetDefaultValue(x => x.ID, “SysGuid()”));


El Mapeo permite llevar a cabo:

– Creación de columnas.

– Establecer PK Simple o Compuesta.

– Establecer Valor Por Defecto.

– Establecer Nulos.

– Establecer Secuencias.

A la hora de realizar una inserción, actualización o borrado, se va a comprobar si existe un mapeo Configurado, en caso de no existir se intentará ejecutar como si tuviese Atributos.

Nuevas formas de Ejecutar Consultas:

Al haber sustituido string por Expression, se ejecutarán las consultas del siguiente modo:

1: var data = db.Query<EMPRESA>(columns:


2: (x) => new { x.EMPR_NOMBRE_CORTO, x.EMPR_NOMBRE_EMPRESA },


3: where:


4: (x => ( x.EMPR_NOMBRE_EMPRESA.Contains(“D”) ||


5: x.EMPR_CODIGO_EMPRESA != 101 ||


6: x.EMPR_AÑO >= 2008 ) && (


7: x.EMPR_MES == 1 )));


Los valores esperados para los parámetros “Columns”, “Where” y “Order”, van a ser expresiones lambda.

 

Finally

Bien como siempre tenéis las descargas en:

GitHub

Nuget

 

Y como siempre cualquier feedback será bien recibido.

Enviado por
Compartir : Compartir en Facebook Compartir en Twitter Compartir en Google+ Compartir en Linkedin
veranete 1 de febrero del 2012 a las 17:09

Hola Javier,

Gracias por la iniciativa.

Aunque no la he empezado a probar, seguro que si lo voy a hacer pronto, pero, recordando, en un post que hiciste de comparativa de ORM ligeros, hablábamos de inserciones batch y que algunos no las tenían; considerarías incluirlo o ya lo tiene ups, por no revisar antes, je,je?

Un abrazo …….

Responder
jtorrecilla 1 de febrero del 2012 a las 19:36

Hola Veranete,

No lo he implementado pero, voy a darle una pensada y a evaluar su rendimiento y si veo buenos resultados lo pongo como feature.

Responder
kiquenet 3 de febrero del 2012 a las 14:33

Muy buena iniciativa, sí.

Hasta ahora utilizamos en el cliente ODP.NET (Oracle.DataAccess) con Ent.Library 4.1, y ahora para .NET 4+VS2010, EntLib 50 + EntLibContrib + Oracle.DataAccess 4.1.

A ver si encuentro hueco para evaluar más ORAPOCO. Si incluye pruebas unitarias facilitaría mucho verlo.

Creo que interesa un ORM ligero, y con soporte para:

parámetros BINARY_FLOAT,BINARY_DOUBLE,BLOB,CLOB
DATE, NUMBER, TIMESTAMP(6), VARCHAR2, UDT’s, XMLTYPE

parámetros IN OUT de tipo SYS_REFCURSOR

Funciones devuelven cursores
FUNCTION GET_EMP_INFO RETURN SYS_REFCURSOR

Múltiples cursores
PROCEDURE GET_MULTIPLE_CURSORS(P_RC1 OUT SYS_REFCURSOR, P_RC2 OUT SYS_REFCURSOR, P_RC3 OUT SYS_REFCURSOR) IS

Table Pipelined Functions
FUNCTION GET_ROWS RETURN OUTPUT_SET PIPELINED

FUNCTION GET_ROWS2 (p_Persona IN UDTPersona) RETURN UDTPersona_Tab PIPELINED is

XMLType
FUNCTION GET_XMLTYPE(num IN NUMBER, xml1 IN XMLTYPE) RETURN XMLTYPE IS

PROCEDURE FRKDATA_TESTXML(qry in VARCHAR2, rslt OUT XMLTYPE) AS

Saludos y muchas gracias.

PD: No me he metido en ello, hay un Oracle Express creo, al estilo de Sql Server Express. Para testing puede ser interesante, en fin son muchos temas que ver.

Responder
jtorrecilla 3 de febrero del 2012 a las 14:38

Hola @Kikenet,
Lo primero gracias por comentar!

A ORAPOCO todavía le queda mucho (o eso espero) por crecer 😀 espero contemplar bastantes de los temas que indicas 😀

Por el tema de pruebas unitarias estoy en ello :-p Me guastaria publicarlas de aqui a 2 semanas aprox!

Responder
anonymous 15 de febrero del 2012 a las 10:28

Continuando con mi particular cruzada de crear un Mini ORM para trabajar con ORACLE, publico una nueva

Responder
Dejar un comentario
Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

Dejar una respuesta

Sin categoría

Tip Rapido: Método Extensor

Bueno aquí va un mini-post. Cuantas veces os habéis encontrado con: if (a>=5 and a<=10) … Yo al menos recuerdo unas pocas. Bueno aquí va el mini truco. Creamos una clase estática con un método extensor: Code Snippet public static class ExtensionMethod  {    public  static bool Between(this int original, int menor, int mayor)      {          return (original […]

Enviado por
Sin categoría

Patrón UoW Parte 2

Introducción En vista de que parece que el artículo que publique ayer sobre UoW, parecía que era demasiado simple…, y a pesar de que Lucas Ontivero ha publicado un ejemplo (Gracias), he decidido publicar un ejemplo un poco más amplio para ver su utilización. Usando el Patrón Partiendo de una clase base: 1: public abstract […]

Enviado por
Sin categoría

[Opinión]Los Nuevos Programadores y VB o C#

Llevo relativamente poco tiempo en el mundo de la programación ya que mis orígenes, los verdaderos, serán del 2001 con C, aunque anteriormente ya había hecho cosas con Visual Basic 6. Por si no lo he dicho nunca, o no me has leído decirlo me encanta programar. Después de la primera introducción voy al hilo […]

Enviado por
Sin categoría

[Personal] Microsoft Community Contributor 2011

En mi revisión matutina del correo, me he encontrado una más que Grata Sorpresa: Dear Javier, Congratulations! We’re pleased to inform you that your contributions to Microsoft online technical communities have been recognized with the Microsoft Community Contributor Award. The Microsoft Community Contributor Award is reserved for participants who have made notable contributions in Microsoft […]

Enviado por
Sin categoría

[Personal] MVP Visual C# 2011

Buenas tardes a todos, Este post es como dice el titulo para anunciar que he sido galordando por el premio MVP de Microsoft en la categoria de C#. Desde aquí quiero darles las gracias a los chicos de Microsoft empezando por Cristina Gonzalez, Jose Bonnin, David Salgado, Boris Armenta… También mi gratitud a la gente de […]

Enviado por