Me pasó muchas veces!!!!
Actualmente tengo que trabajar con una aplicación web que se conecta a una ase de datos. Esta aplicación la creó un desarrollador hace mucho tiempo.
Bien mi misión esta vez era realizar un registro de varios campos de la aplicación para una vista que necesitaba negocio. Necesito enviarle al DBA los campos y las tablas de dichos campos. Este formulario tiene cerca de 300 campos!!!!
Ahora buscar cada campo de la base de datos correspondiente a cada campo en la aplicación... en una base de datos de muchas tablas, de muchos campos cada una... antes de empezar a buscar uno por uno recordé que alguna vez tuve un query que me ayudaba a realizar esta búsqueda de manera muy sencilla, utilizando las tablas INFORMATION_SCHEMA.TABLES y INFORMATION_SCHEMA.COLUMNS.
Con este sencillo query puedo buscar por nombre de tabla o de columna:
SELECT
T.TABLE_NAME AS 'TABLE NAME',
C.COLUMN_NAME AS 'COLUMN NAME'
FROM INFORMATION_SCHEMA.TABLES T
INNER JOIN INFORMATION_SCHEMA.COLUMNS C ON T.TABLE_NAME=C.TABLE_NAME
WHERE T.TABLE_TYPE='BASE TABLE'
con solo colocar un par de condicionales como los siguientes:
AND T.TABLE_NAME LIKE '%Issues%'
AND C.COLUMN_NAME like '%NEM%'
podremos encontrar por ejemplo los nombres de la tabla o de los campos.
La demora fué meramente operativa, pues con este query y un poco de intuición para buscar los campos, pude solucionar este lío.
Como siempre, siéntanse libres de dejar sus comentarios
lunes, 16 de noviembre de 2015
jueves, 12 de febrero de 2015
SSIS Data Conversion Que pasó? Antes eras Chévere!!!!
Buenas buenas :)
bien, el día de hoy les hablaré de un componente de SSIS llamado Data Conversion. Como bien saben en algunos casos, nuestros hermosos clientes tienen en sus bases de datos tablas que tienen columnas, que tienen tipos de datos (quetienen, que tienen, que tienen...).
Lo normal es que esos tipos de datos tengan un manejo natural de algunas cosas que para uno de developer son muy obvias. Ejemplo, si tengo un UnicodeString de lenght 255 y tengo que meterlo a un string de 50, bueno, es solo usar el componente para convertir, cambiar el tamaño y todos somos felices.
Bueno, SSIS en su maratón por ponerme a pensar, me empezó a generar errores en este componente.
Después de mucho meditar, pensar y a punto de arrojar el pc por la ventana, me dí cuenta que el error estaba al realizar exactamente ese tipo de conversión. Ojo, no siempre sucede, pero en caso que apareciera el error descrito en la segunda imágen o incluso cuando sale el horroroso Exception from HRESULT: 0xC0047020 debería ser este caso.
Bien, solución? decidí quitar el Data Conversion y lo cambié por un Derived Column. Para la conversión de datos usé el Cast, dándole el tipo de dato requerido y el lenght correcto. El resultado fué un error por truncamiento. Que se hace en este caso? poner un Substring al campo
Con esto solucionamos el problema. Si se dan cuenta incluso el Warning desapareció.
Bueno. En algunos casos el mejor camino a encontrar el error que aparece (cuando no es específico) lo mejor es ver los warnings. Diría un amigo mío, "los warnings no son chisme" estos si bien no nos dicen que es el error en sí, nos pueden ayudar mucho a encontrarlo, sobretodo en SSIS ya que este no posee un proceso de debugging (al cual los developers estamos acostumbrados).
Como una recomendación, si estás empezando con SSIS, es muy importante, que llegues a un nivel de ver campo por campo de las fuentes y destino de tu integración, esto con el fin de que tenga una coherencia el proceso y no tengas dolores de cabeza. Siempre recuerda amigo developer, ya no estás en C#!!!! estás en Pandora... perdón en SSIS, y si quieres que tu integración funcione a la perfección, lo más importante es tener muy en cuenta tanto los tipos de dato y como el tamaño de los mismos.
Como siempre, cualquier inquietud, siéntanse libres de escribir sus comentarios.
Un abrazo
Piojo dev
bien, el día de hoy les hablaré de un componente de SSIS llamado Data Conversion. Como bien saben en algunos casos, nuestros hermosos clientes tienen en sus bases de datos tablas que tienen columnas, que tienen tipos de datos (quetienen, que tienen, que tienen...).
Lo normal es que esos tipos de datos tengan un manejo natural de algunas cosas que para uno de developer son muy obvias. Ejemplo, si tengo un UnicodeString de lenght 255 y tengo que meterlo a un string de 50, bueno, es solo usar el componente para convertir, cambiar el tamaño y todos somos felices.
Bueno, SSIS en su maratón por ponerme a pensar, me empezó a generar errores en este componente.
Después de mucho meditar, pensar y a punto de arrojar el pc por la ventana, me dí cuenta que el error estaba al realizar exactamente ese tipo de conversión. Ojo, no siempre sucede, pero en caso que apareciera el error descrito en la segunda imágen o incluso cuando sale el horroroso Exception from HRESULT: 0xC0047020 debería ser este caso.
Bien, solución? decidí quitar el Data Conversion y lo cambié por un Derived Column. Para la conversión de datos usé el Cast, dándole el tipo de dato requerido y el lenght correcto. El resultado fué un error por truncamiento. Que se hace en este caso? poner un Substring al campo
Con esto solucionamos el problema. Si se dan cuenta incluso el Warning desapareció.
Bueno. En algunos casos el mejor camino a encontrar el error que aparece (cuando no es específico) lo mejor es ver los warnings. Diría un amigo mío, "los warnings no son chisme" estos si bien no nos dicen que es el error en sí, nos pueden ayudar mucho a encontrarlo, sobretodo en SSIS ya que este no posee un proceso de debugging (al cual los developers estamos acostumbrados).
Como una recomendación, si estás empezando con SSIS, es muy importante, que llegues a un nivel de ver campo por campo de las fuentes y destino de tu integración, esto con el fin de que tenga una coherencia el proceso y no tengas dolores de cabeza. Siempre recuerda amigo developer, ya no estás en C#!!!! estás en Pandora... perdón en SSIS, y si quieres que tu integración funcione a la perfección, lo más importante es tener muy en cuenta tanto los tipos de dato y como el tamaño de los mismos.
Como siempre, cualquier inquietud, siéntanse libres de escribir sus comentarios.
Un abrazo
Piojo dev
sábado, 7 de febrero de 2015
Modelos, modelos... ojo con los modelos!!!!!
El día de hoy estaba terminando una implementación, para la interfaz de un proyecto en MVC. Consiste en un módulo que lee una tabla en una base de datos de una aplicación de integración y la idea es que esta tiene una configuración que se trabaja desde mi portal.
Tenía entonces un lindo ViewModel encargado de llevar la información de la vista al controlador... esa carreta la conocen verdad? en caso que la respuesta sea un no, visiten el siguiente link.
Bueno, todo iba de perlas hasta que tuve que hacer la parte POST del controlador. Al ejecutar el submit me aparecía el siguiente error:
me devané los sesos buscando la solución al problema y como en la mayoría de mis errores, era una cosa muy pequeña.
Supongamos que uds manejan un viewmodel para la comunicación que tiene un constructor de tipo:
public MyViewModel(MyObjectType myViewModel)
{
Property1 = myViewModel.Property1;
Property2 = myViewModel.Property2;
Property3 = myViewModel.Property3;
}
Bien, en caso que ese sea su único constructor, MVC se enloquece buscando uno sin parámetros (aún no entiendo a ciencia cierta muy bien el por qué). Bueno la solución es super sencilla. Solo es necesario crear un constructor vacío (o por lo menos uno sin parámetros) de la siguiente manera:
public MyViewModel()
{
}
de este modo al tener el constructor vacío, todo funciona correctamente.
Dicen por ahí... "hasta ahí, normal."
Ahora, por qué me tomó tanto tiempo encontrar el error? Bien, un problema que sucede muy a menudo es cuando un ViewModel en nuestra aplicación tiene más ViewModel's uno dentro de otro, es decir un ViewModel anidado. Cuando estos modelos tienen cierta complejidad, la cosa se pone aún más difícl de detectar.
Bueno, si hubiese tenido en cuenta ese pequeño detalle en el ViewModel, seguramente no hubiese sido víctima de esa improductiva labor de encontrar el bug.
Así que tengan cuidado mis amigos... este tipo de situaciones nos conllevan mucho tiempo de solución y normalmente el problema es una bobada.
Como siempre, siéntanse en total libertad de comentar.
Un Abrazo
PiojoDev
Tenía entonces un lindo ViewModel encargado de llevar la información de la vista al controlador... esa carreta la conocen verdad? en caso que la respuesta sea un no, visiten el siguiente link.
Bueno, todo iba de perlas hasta que tuve que hacer la parte POST del controlador. Al ejecutar el submit me aparecía el siguiente error:
me devané los sesos buscando la solución al problema y como en la mayoría de mis errores, era una cosa muy pequeña.
Supongamos que uds manejan un viewmodel para la comunicación que tiene un constructor de tipo:
public MyViewModel(MyObjectType myViewModel)
{
Property1 = myViewModel.Property1;
Property2 = myViewModel.Property2;
Property3 = myViewModel.Property3;
}
Bien, en caso que ese sea su único constructor, MVC se enloquece buscando uno sin parámetros (aún no entiendo a ciencia cierta muy bien el por qué). Bueno la solución es super sencilla. Solo es necesario crear un constructor vacío (o por lo menos uno sin parámetros) de la siguiente manera:
public MyViewModel()
{
}
de este modo al tener el constructor vacío, todo funciona correctamente.
Dicen por ahí... "hasta ahí, normal."
Ahora, por qué me tomó tanto tiempo encontrar el error? Bien, un problema que sucede muy a menudo es cuando un ViewModel en nuestra aplicación tiene más ViewModel's uno dentro de otro, es decir un ViewModel anidado. Cuando estos modelos tienen cierta complejidad, la cosa se pone aún más difícl de detectar.
Bueno, si hubiese tenido en cuenta ese pequeño detalle en el ViewModel, seguramente no hubiese sido víctima de esa improductiva labor de encontrar el bug.
Así que tengan cuidado mis amigos... este tipo de situaciones nos conllevan mucho tiempo de solución y normalmente el problema es una bobada.
Como siempre, siéntanse en total libertad de comentar.
Un Abrazo
PiojoDev
jueves, 22 de enero de 2015
Excel y SSIS, pare de sufrir usando LinqToExcel
"como dijo el borracho a la monja... esperaba más de tí batman..."
Bueno, dado que en mi empresa soy el desarrollador de integraciones y afines me solicitaron hacer un ingreso masivo de datos a una BD, hacerle un tratamiento de limpieza y tomar todos los datos a un consumo mounstruoso de un WCF. Todo pintaba bien, una solución SSIS que hiciera todo el proceso y una vez finalizara la limpieza empezar a darle a ese wcf como si no hubiera un mañana. Obvio, primero me aseguré que no hubiese un cuello de botella en el servicio wcf, pero después de ver que el servicio estaba en una plataforma de alta disponibilidad y dado que es un proceso nocturno, no le ví problema. Lástima que el acceso a la BD estuviese restringido, todo hubiese sido más chévere.
En fin inicié el proceso así que lo primero que hice fué revisar la fuente y oh sorpresa!!! un archivo excel. No era novedad para mí, pero siempre he desconfiado de cuando la fuente es un excel, no es la primera vez que sufro con el tema.
Lo primero que me advirtieron es que el archivo no se podía manipular de manera manual (usuarios, esas bellas criaturas que nos proveen el salario pero que nos hacen salir canas verdes....). Esta parte del proceso me auguraba cosas muy complicadas en mi integración. En efecto me salió un problemita bastante molesto de solucionar.
Al crear un Excel Source, el Excel Connection Manager tomaba aparentemente bien los campos, sin embargo aveces me traía unos datos nulos que en el archivo si venían con información. Cuando empecé a diagnosticar el problema, lo primero que noté es que la columna que generaba el lío con los nulos tiene una combinación entre datos numéricos y datos alfanuméricos. Resulta que según el siguiente post, el amigo Excel Source revisa los primeros ocho campos y decide el tipo de dato por mí (tan proactivo el amigo).
Resulta que si el tipo de dato que detecta es numérico, los datos alfanuméricos los vuelve null. La solución obvia era manipular el archivo, pasar la columna a texto y todos somos felices... pero en mi caso no es posible, el archivo no puede tener interacción humana.
Intenté con las soluciones de este post https://social.msdn.microsoft.com/Forums/sqlserver/en-US/54dc94c5-280b-41e5-82fe-26925f9eb95b/ssis-excel-data-source-numeric-values-returned-as-null
primero con la cadena de conexión agregando la línea IMEX=1; pero no funcionó... seguí revisando y la otra opción era hacer un cambio en la llave HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Excel en el registro de la máquina.
http://sqlcastle.weebly.com/ssis/in-ssis-excel-data-source-column-values-are-returned-as-null
Ya me imaginaba yo a los de IT peleando por la manipulación del registro, por lo que tampoco representaba una solución viable para mí.
Continuando con mi investigación, encontré que tanto en stack overflow como en MS me daban solo la solución de manipular el archivo. Aquí los links:
Bueno, dado que en mi empresa soy el desarrollador de integraciones y afines me solicitaron hacer un ingreso masivo de datos a una BD, hacerle un tratamiento de limpieza y tomar todos los datos a un consumo mounstruoso de un WCF. Todo pintaba bien, una solución SSIS que hiciera todo el proceso y una vez finalizara la limpieza empezar a darle a ese wcf como si no hubiera un mañana. Obvio, primero me aseguré que no hubiese un cuello de botella en el servicio wcf, pero después de ver que el servicio estaba en una plataforma de alta disponibilidad y dado que es un proceso nocturno, no le ví problema. Lástima que el acceso a la BD estuviese restringido, todo hubiese sido más chévere.
En fin inicié el proceso así que lo primero que hice fué revisar la fuente y oh sorpresa!!! un archivo excel. No era novedad para mí, pero siempre he desconfiado de cuando la fuente es un excel, no es la primera vez que sufro con el tema.
Lo primero que me advirtieron es que el archivo no se podía manipular de manera manual (usuarios, esas bellas criaturas que nos proveen el salario pero que nos hacen salir canas verdes....). Esta parte del proceso me auguraba cosas muy complicadas en mi integración. En efecto me salió un problemita bastante molesto de solucionar.
Al crear un Excel Source, el Excel Connection Manager tomaba aparentemente bien los campos, sin embargo aveces me traía unos datos nulos que en el archivo si venían con información. Cuando empecé a diagnosticar el problema, lo primero que noté es que la columna que generaba el lío con los nulos tiene una combinación entre datos numéricos y datos alfanuméricos. Resulta que según el siguiente post, el amigo Excel Source revisa los primeros ocho campos y decide el tipo de dato por mí (tan proactivo el amigo).
Resulta que si el tipo de dato que detecta es numérico, los datos alfanuméricos los vuelve null. La solución obvia era manipular el archivo, pasar la columna a texto y todos somos felices... pero en mi caso no es posible, el archivo no puede tener interacción humana.
Intenté con las soluciones de este post https://social.msdn.microsoft.com/Forums/sqlserver/en-US/54dc94c5-280b-41e5-82fe-26925f9eb95b/ssis-excel-data-source-numeric-values-returned-as-null
primero con la cadena de conexión agregando la línea IMEX=1; pero no funcionó... seguí revisando y la otra opción era hacer un cambio en la llave HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Excel en el registro de la máquina.
http://sqlcastle.weebly.com/ssis/in-ssis-excel-data-source-column-values-are-returned-as-null
Ya me imaginaba yo a los de IT peleando por la manipulación del registro, por lo que tampoco representaba una solución viable para mí.
Continuando con mi investigación, encontré que tanto en stack overflow como en MS me daban solo la solución de manipular el archivo. Aquí los links:
Dado que el tiempo apremiaba solo se me ocurrió manipular el archivo de manera automática. Encontré entonces algo muy interesante.
Pensé en crear una aplicación de consola que me permitiera la manipulación del archivo trnsformádolo en uno plano (csv o txt separado por tabs). encontré entonces una hermosa librería llamada LinqToExcel.
Esta librería es genial por que me permite hacer una manipulación brutal del archivo sin mayor complique. El desarrollo del componente no me tomó más de dos horas (contando la curva de aprendizaje del uso del componente) así que solo me quedaba enfrentarme al tema del rendimiento. Cual sería mi sorpresa cuando leyendo registro por registro, campo por campo, logré pasar 31.118 registros en 10 segundos aproximadamente (contando con que mi máquina de desarrollo no es un servidor realmente).
creé la librería para la manipulación de acuerdo a mis necesidades y funcionó correctamente. Aquí el código:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LinqToExcel;
using System.IO;
using System.Web;
namespace ExcelManager
{
public class ExcelManager
{
public string FilePath { get; set; }
public string FlatFilePath { get; set; }
public string SheetName { get; set; }
public string FileExtension { get; set; }
public string Delimitator { get; set; }
public string CreateCsv()
{
string sResult = string.Empty;
try
{
DateTime horainicio = DateTime.Now;
FileInfo resultFile = new FileInfo(FlatFilePath + "." + FileExtension);
StreamWriter writer;
if (!resultFile.Exists)
{
writer = resultFile.CreateText();
writer.Close();
}
else
{
resultFile.Delete();
}
var excelFile = new ExcelQueryFactory(FilePath);
List<string> workSheets = excelFile.GetWorksheetNames().ToList();
var data = (from a in excelFile.Worksheet(workSheets[0])
select a).ToList();
string sdata = string.Empty;
writer = new StreamWriter(resultFile.FullName);
foreach (var item in data)
{
for (int i = 0; i < item.Count - 1; i++)
{
if (i < item.Count - 2)
sdata += fixText(item[i]) + Delimitator.ToString();
else
sdata += fixText(item[i]);
}
writer.WriteLine(sdata);
sdata = string.Empty;
}
DateTime horafin = DateTime.Now;
TimeSpan tspan = horafin.Subtract(horainicio);
sResult = writer.Encoding.EncodingName + " " +tspan.Seconds.ToString();
writer.Close();
}
catch (Exception ex)
{
sResult = ex.Message;
//throw;
}
return sResult;
}
private string fixText(Cell cell)
{
string sResultText = string.Empty;
sResultText = System.Web.HttpUtility.HtmlDecode(cell.Value.ToString()).Trim();
return sResultText;
}
}
}
La librería LinqToExcel se puede instalar desde NuGet... así o mas contento?
Ahora verán un método llamado fixText. Resulta que el archivo traía caracteres locos en lugar de tildes o el caracter "Ñ" o "ñ". revisando, el caracter es de tipo html encoding. Cinco minutos de revisión encontré como solucionar el tema usando la System.Web.HttpUtility que con el método HtmlDecode me convertía el campo en un string normalito. Con esto pude solucionar el inconveniente.
Sigo insistiendo para ver si MS da una solución más "natural" al problema.
cualquier inquietud adicional, siéntanse libres de dejar sus comentarios.
Un abrazo
Piojo Dev
Suscribirse a:
Entradas (Atom)








