domingo, 22 de enero de 2012

Problema con Eclipse+jdk Debian Squeeze

Hola a todos, bueno aunque esta es una entrada un tanto diferente a las que generalmente y en un sistema operativo diferente, aca va.

Decidí aprender a desarrollar en android, esta vez de verdad y sin interrupciones, y bajo un entorno GNU/Linux, actualmente la distribucion que utilizo es Debian Squeeze, pues bien, estos fueron los problemas que tuve:

1. Después de instalar jdk, instalé el .bin que descargue de la web de oracle, después de esta instalación siempre tengo la costumbre de probar el compilador desde una terminal, pero luego para mi asombro :) me di cuenta que cuando escribía javac en la terminal me salía un mensaje de comando no encontrado, pero eso era falso ya que tenia instalado el jdk en /opt/jdk1.6.0_16/, luego buscando por internet encontré que tenia que establecer algunas variables de entorno, para lo cual editando el archivo /etc/bash.bashrc como root adicioné las siguientes lineas


# Establece la ruta del jdk
export JAVA_HOME=/opt/jdk1.6.0_16/ 

# Establece el directorio donde se encuentra el compilador
export PATH=$PATH:$JAVA_HOME/bin

# Establece el directorio donde se encuentran los binarios del JRE
export PATH=$PATH:$JAVA_HOME/jre/bin


Y bueno, con eso ya solucioné el problema que tenia en la terminal, super. Pero luego tuve otro problema, descargue el empaquetado de eclipse desde su web, de la misma forma que el jdk, esta vez los descomprimí en /opt/eclipse, lo ejecute por terminal


$ ./eclipse


Y se ejecuto tranquilamente, luego por cuestiones de comodidad, quise ponerlo en mi panel de accesos directos, establecí la ruta del ejecutable pero otra sorpresa, me salía un mensaje de error que podía encontrar ningún JRE instalado, lo cual era falso, y en el mensaje de error aparecía la siguiente ruta /opt/eclipse/jre/bin/java, obviamente no tenia ese directorio donde estaba instalado eclipse, entonces sabiendo que el JRE estaba en la carpeta del jdk, decidí crear un enlace simbólico del /bin del JRE a la carpeta de eclipse, esto ejecutando los siguientes comandos:


# mkdir /opt/eclipse/jre
# ln -s /opt/jdk1.6.0_16/jre/bin /opt/eclipse/jre/


Al no ser desarrollador java (siento que es la peor excusa), y menos en un entorno GNU/Linux, no estoy seguro que esta si esto puede ser considerado o no una buena práctica, pero funcionó por mi, todo en mi afán de intentar aprender a desarrollar aplicaciones para android.

Bueno, espero que les sea de utilidad.

Saludos

sábado, 17 de diciembre de 2011

Utilizando Reflection para el Acceso a Datos

Hola a todos, pues hace tiempo programe una clase utilitaria para automatizar la transformación de objetos ADO.Net que contenian información recuperada de una fuente de datos a POCO (Plain Old CLR Objects) utilizando reflection. Pues sin nada que hacer este sábado por la noche, decidí escribir este post sobre este DataTransformer

Primero comentar que reflection es el proceso en el cual un programa puede modificar su propia estructura en tiempo de ejecución (gracias wikipedia). Bueno esto se lo puede entender de muchas formas, pero un ejemplo simple sería el de crear la instancia de una clase cualquiera en tiempo de ejecución, por ejemplo pasandole como parámetro el nombre de esta, tal vez es un poco abstracto comprender esto pero en wikipedia hay un ejemplo muy bueno, que prácticamente hace la creación de un objeto de la forma clásica y utilizando reflection:


//Without reflection
Foo foo = new Foo();
foo.Hello();

//With reflection
object foo = Activator.CreateInstance(null, "Foo");
foo.GetType().GetMethod("Hello").Invoke(foo, null);

Ahora, como podríamos aplicar esto para automatizar el acceso a datos?, primeramente, esto se aplica en caso que nuestra capa de acceso a datos no cuente con un ORM. Siempre se dará el caso que una empresa requiera que la capa de acceso a datos se realice utilizando Ado.net puro y no un ORM, de todos modos, si nuestra aplicación tiene una arquitectura por lo menos de tres capas, se realizará un mapeo manual de los objetos ado.net a nuestro POCO, por ejemplo:


 public List<Persona> GetPersonas() {
  SqlConnection conn = new SqlConnection(Config.GetDbString("mibase"));
  string sql = "SP_GetPersonas";
  SqlDataAdapter adapter = new SqlDataAdapter(sql, conn);
  
  DataTable personas = new DataTable();
  
  try {
   adapter.Fill(personas);
   List<Persona> result = new List<Persona>();
   foreach(DataRow row in personas.Rows) {
    Persona temp = new Persona();
    temp.Codigo = row["Codigo"].ToString();
    temp.Nombre = row["Nombre"].ToString();
    
    result.Add(temp);
   }
   
   return result;
  }
  catch(Exception ex) {
   throw ex;
  }
 }

Como se ve en el ejemplo, basicamente se esta haciendo un mapeo manual de una estructura DataTable a un objeto de tipo Persona, hasta aca todo simple, yo no me haria problema si tengo que hacer esto para 10 tablas, pero las estructuras empresariales pueden ser de decenas de decenas de tablas, sin incluir vistas. Entonces aca es donde entra reflection, para crear objetos dinámicamente.

Al siguiente clase como lo mencione arriba, realiza la transformación de una objeto Ado.net en un POCO, básicamente crea la instancia de un objeto que yo especifico, recorre sus propiedades y las compara con el nombre de las columnas de nuestro objeto Ado.net, si coinciden asigna el valor del objeto Ado.net a nuestro POCO.

Este es el código de DataTransformer:


public static class DataTransformer {
        /// <summary>
        /// Realiza la conversión de un DataTable a 
        /// una lista genérica de tipo TargetType
        /// </summary>
        /// <typeparam name="TargetType">Tipo destino de la lista</typeparam>
        /// <param name="table">Origen de datos</param>
        /// <returns>Lista genérica</returns>
        /// <exception cref="Exception: En caso que los tipos del origen de datos no coincidan 
        /// con los de TargetType"></exception>
        public static List<TargetType> DataTableToGenericList<TargetType>(DataTable table) {
            List<TargetType> resultList = new List<TargetType>();
            DataColumn temp;
            TargetType item;

            item = Activator.CreateInstance<TargetType>();
            PropertyInfo[] properties = item.GetType().GetProperties();

            foreach (DataRow row in table.Rows) {
                item = Activator.CreateInstance<TargetType>();
                foreach (PropertyInfo property in properties) {
                    temp = table.Columns[property.Name];
                    if (temp != null) {
                        if (temp.DataType.Name.Equals(property.PropertyType.Name)) {
                            property.SetValue(item, row[temp], null);
                        }
                        else {
                            throw new Exception("El tipo de la propiedad y columna son diferentes.");
                        }
                    }
                }
                resultList.Add(item);
            }
            return resultList;
        }
        /// <summary>
        /// Realiza la conversión de un IDataReader a 
        /// una lista genérica de tipo TargetType
        /// </summary>
        /// <typeparam name="TargetType">Tipo destino de la lista</typeparam>
        /// <param name="reader">Origen de datos</param>
        /// <returns>Lista genérica</returns>
        /// <exception cref="Exception: En caso que los tipos del origen de datos no coincidan 
        /// con los de TargetType"></exception>
        public static List<TargetType> DataReaderToGenericList<TargetType>(IDataReader reader) {
            List<TargetType> resultList = new List<TargetType>();
            object propertyValue;
            int columnNumber = reader.FieldCount;
            TargetType item;

            item = Activator.CreateInstance<TargetType>();
            PropertyInfo[] properties = item.GetType().GetProperties();

            while (reader.Read()) {
                item = Activator.CreateInstance<TargetType>();
                foreach (PropertyInfo property in properties) {
                    for (int i = 0; i < columnNumber; i++) {
                        if (reader.GetName(i).ToLower().Equals(property.Name.ToLower())) {
                            if (reader.GetFieldType(i).Name.Equals(property.PropertyType.Name)) {
                                propertyValue = reader.GetValue(i);
                                property.SetValue(item, propertyValue, null);
                                break;
                            }
                            else {
                                throw new Exception("El tipo de la propiedad y columna son diferentes.");
                            }
                        }
                    }
                }
                resultList.Add(item);
            }
            return resultList;
        }

        public static TargetType DataTableToObject<TargetType>(DataTable table) {
            List<TargetType> lista = DataTableToGenericList<TargetType>(table);
            if (lista.Count > 0)
                return lista[0];
            else
                return default(TargetType);
        }
    }

Analicemos un poco el método DataTableToGenericList. Primero notar que recibe como parámetro el objeto Ado.net del cual queremos transformar los datos, luego tenemos el tipo al cual queremos transformar, obviamente este tipo tiene que ser POCO. Luego se crea una lista de objetos del tipo que se nos da como parametro, luego obtiene en un arreglo de tipo PropertyInfo las propiedades de este objeto.

Finalmente recorre las filas del DataTable, y por cada fila, recorre el arreglo que contiene las propiedades y las compara con las columnas del DataTable y voila!!

Una vez que tenemos este transformador de datos, nuestro código para obtener una lista de personas, tendríamos lo siguiente:


 public List<Persona> GetPersonas() {
  SqlConnection conn = new SqlConnection(Config.GetDbString("mibase"));
  string sql = "SP_GetPersonas";
  SqlDataAdapter adapter = new SqlDataAdapter(sql, conn);
  
  DataTable personas = new DataTable();
  
  try {
   adapter.Fill(personas);
   return DataTransformer.DataTableToGenericList<Persona>(personas);
   
   return result;
  }
  catch(Exception ex) {
   throw ex;
  }
 }

Y como pueden observar, ya no es necesario mapear los objetos manualmente.

Bueno, eso es todo para esta entrada, ya me cayo el sueño, espero les sea de utilidad.

Saludos

jueves, 1 de diciembre de 2011

Mis primeros pasos con Web Matrix

Hola a todos, pues bien, una de las tareas que mi amigo asigno fue la de ver y mostrar lo que respecta uso la siguientes tecnologías:
  • Web Matrix
  • Azure
  • Windows Phone 7
Pues bien, Azure nunca lo toque además que tampoco tengo SDK, lo se error mío. WP7 lo estoy viendo de a poco y Web Matrix es algo nuevo para mí, por lo que leí en me parece una buena herramienta, por el hecho que el desarrollo y deployment de sitios web y que opera (no se si es el mejor término), con plataformas como GNU/Linux.

En este momento lo estoy descargando y en el wizard de instalación se da la opción de instalar aplicaciones tales como CMS, Wikis, Blog engines, etc, etc. Una herramienta muy completa. Otra de las cosas que me llama la atención y que pude observar en el video de 3 minutos que se muestra en
el sitio de Web Matrix es el hecho de utilizar Razor para los sitios, pues bien, esto me impulsa mas a aprender el uso de esta herramienta, ya que en un futuro quiero aprender a utilizar ASP.NET MVC y hasta donde se, el View Engine de este framework es Razor.

En los siguientes días ire aumentando nuevas entradas para mostrar algunas de las cosas que logré hacer con Web Matrix.

Saludos!

sábado, 26 de noviembre de 2011

Nuevos Horizontes

Hola a todos, varias cosas raras ocurrieron en mi vida estos ultimos días,
tuve que decidir varias cosas, analizar las consecuencias de cada una de
mis decisiones, pero al final, en lo personal creo que tome la mejor decision.

Ahora, tengo que dedicarme a full a la actividad que decidí continuar, es decir
los Student Tech Clubs :)

Ahora las actividades que se vayan realizando con los Student Tech Clubs de la
Universidad Mayor de San Andrés, y los de Bolivia los iré publicando aca. En estas
semanas se me encargó la creación del sitio (nuevo reto para mí), el cual tendrá
la información sobre los STCs en Bolivia.

Saludos