23 jul 2009

¿Múltiples Webservices o un único con muchos Webmethods?

Mi amigo Natacuin, gran programador aunque últimamente más del lado de la administración, planteo hace poco esa pregunta: se debe utilizar un único webservices con muchos webmethods o es preferible por rendimiento partirlos en varios webservices con menos webmethods.

El mismo Natacuin buscó su respuesta planteándose un escenario y una serie de pruebas reseñables las cuales se encuentran en esta entrada de su blog para consulta y mayor detalle.

La conclusión a la que llegó es que "Las diferencias existen pero no son abismales, lo que significa que para que el rendimiento sea un factor a tomar en cuenta, los request por segundo al sistema deben ser miles ". Y que la recomendación es que es preferible usar múltiples webservices, lo cual también puede redundar en otros beneficios como en un mayor orden ya que se pueden agrupar en un webservice los webmethod afines, logrando asu vez facilidad de mantenimiento e incluso de programación por cuanto se pueden atender varios webmethods por varias personas sin pensar en la consistencia del código en el caso de que no se contase con una herramienta que lo controle por nosotros.

11 jul 2009

OLEDB para cargar archivos de excel

Recientemente debíamos cargar un archivo al servidor y cargar sus celdas en una base de datos. Ademas debíamos cumplir el requerimiento de no instalar ningún componente de MS Office en los servidores.

Como sugerencia del departamento de sistemas del cliente se nos indicó que utilizáramos Dtsx para realizar esa operación y de hecho llegamos un solución con paquetes SSIS. Sin embargo se nos complicó por una cuestión de permisos. Finalmente optamos por hacer una solución basada en OleDB más sencilla y más fácil para darle mantenimiento.

¿Y el rendimiento? pues ninguna diferencia porque resulta que los Dtsx para manejar excel utiliza OleDb. He aquí parte de la solución con .Net y OleDB

Primeramente recordar usar este using:
 using System.Data.OleDb;

Todo el secreto esta en la conexión
   OleDbConnection cnnOle = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:Pruebas\test.xls;Extended Properties=\"EXCEL 8.0;HDR=NO;IMEX=1\";");
   cnnOle.Open();  

Aqui hay varios aspectos a tomar en cuenta:
- Primeramente el Data Source puede ser tanto una carpeta local, como en este caso, o bien una carpeta compartida o DFS (p.e. \\DFS\Pruebas\test.xls)

- Lo que vamos a hacer es una consulta SQL del Excel por lo que si en Extended Properties indicamos que HDR=YES, estamos diciendo que el primer valor de las celdas es el nombre con el que se conoceran las columas. Asi si tenemos un excel en el primer valor de cada columna, o encabezado, es PRODUCTO, CANTIDAD, PRECIO entonces podriamos hacer:
SELECT PRODUCTO, CANTIDAD, PRECIO FROM [Sheet1$]
Pero si usamos HDR=NO, usamos el nombre generico (F1, F2.,..) de las columnas, incluyendo, obviamente, el primer valor de cada columna como valores que nos devolvera la consulta

-Ademas debemos tener en cuenta que el IMEX=1 en Extended Properties significa que se tomaran los valor tal y como se FORMATEAN en las celdas, esto es muy importante porque por ejemplo si el valor de la celda es un número, supongamos 1000000 y se encuentra formateado como monto (1,000,000.00) es posible que sea mejor eliminar el tag IMEX del todo para usar el valor real de la celda en lugar del ya formateado para evitar errores de conversión de tipos.

Seguidamente hacemos la consulta:
DataTable schemaTable = cnnOle.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });

OleDbCommand cmdOle = new OleDbCommand("SELECT F1,F2,F3  FROM [" + schemaTable.Rows[0]["Table_Name"].ToString() + "]", cnnOle);

OleDbDataAdapter daOle = new OleDbDataAdapter(cmdOle);
dt = new DataTable();
daOle.Fill(dt);


La primera instrucción lo que hace es extraer en un DataTable el schema del excel para poder sacar el nombre de las hojas, esto es importante porque en el si Excel esta en español las hojas se denominan Hoja1$, Hoja2$, etc.. y si esta ingles Sheet1$, Sheet2$, etc ademas puede tener un nombre personalizado y con esta instrucción podemos desentendernos de este aspecto.

Las demás instrucciones realizan la consulta usando OleDbCommand y OleDbDataAdapter para dejar la información que necesitamos en un DataTable y a partir de que lo podemos manipular como mejor nos convenga

Gracias una vez más a Pigo Sama por su inmensa sabiduría.