Thursday, July 31, 2008

MARS MultipleActiveResultSets True

Cuando estas trabajando con SqlDataReader para obtener informacion del SQL Server 2005 muy probablemente te encuentres con este mensaje al ejecutar el metodo ExecuteReader del SqlCommand:

There is already an open DataReader associated with this Command which must be closed first.

En terminos sencillos, se nos dice, que ya tenemos un SqlDataReader que se encuentra abierto y NO seria posible aperturar otro al mismo tiempo, mientras NO se cierre el primero.

Para este incidente, el SqlServer2005 brinda la posibilidad de agregar una propiedad al ConnectionString para permitir multiples SqlDataReader abiertos, al mismo tiempo.

Agregando MultipleActiveResultSets=True al ConnectionString se resuelve el problema.

Sin embargo recuerda que esta facilidad solo esta permitida en SQL Server 2005 y superiores.

En la version del SQL Server 2000 esta propiedad para el ConnectionString NO esta factible de utilizar. Por lo que el error aun prevalecera.

Monday, July 28, 2008

SetValue PropertyInfo FieldInfo Struct

Cuando defines tus Business Entities como structuras y NO como clases, es decir como struct.

Estableciendo sus diferentes atributos, para que posteriormente manejar el mapping correcto con su correspondiente tabla a nivel de base de datos, requeriras de una mecanismo generico para hacer la lectura de los registros de dicha tabla de base de datos hacia una coleccion de Business Entities, para manejarlos como tal dentro del mundo .NET

Hasta alli, todo relativamente normal.

Pero al usar un struct para definir cierto Business Entity, te daras cuenta que el metodo SetValue del PropertyInfo o el FieldInfo -dependiendo lo que estes usando para definir las propiedades o atributos de tu Business Entity- NO estan funcionando como tu esperas.

Lo que sucede es que las estructuras o struct, son tipos de datos por valor a diferencia de las clases o class.

Y este es uno de los puntos en contra al utilizar estructuras o struct para definir tus Business Entities.

En este incidente la clase ValueType resuelve tu problema.

TEntity entity = new TEntity();

Debera ser reemplazado por:

ValueType entity = new TEntity();

Dentro del bucle que este leyendo el SqlDataReader para iterar cada uno de los registros de la consulta que hayas realizado, mapeando cada uno de estos registros dentro de su Business Entity para retornar finalmente a una coleccion de Business Entities, a quien haya utilizado el metodo generico que implementaste.

IEnumerable ExecuteReader( String sql ) where TEntity : struct

Vale recalcar que es importante utilizar la clausula where TEntity : struct para poder instanciar el template TEntity dentro de la implementacion de dicha funcion y para poder castearlo a un ValueType, posteriormente.

Wednesday, July 23, 2008

Top Down versus Bottom Up

Cuando desarrollamos software con conectividad a Base de Datos, nos encontramos con diferentes herramientas, en el mercado, que facilitan la construccion de los Business Entities a partir de una estructura de datos relacional.

El resultado es alentador. Gracias al Drag & Drop o algo relativamente similar obtenemos los Business Entities para el mundo .NET desde el conjunto de tablas que se encontraban ya definidas en la Base de Datos.

Esta es una perspectiva Bottom-Up.

Pues partimos del nivel mas bajo de la arquitectura de un producto de software, la Base de Datos, para facilitar la contruccion de las demas capas de la arquitectura, aquellas que estan por encima de la Base de Datos.

Pero existe la posicion contraria. Un punto de vista distinto, llamado Top Down.

A partir del cual prototipeamos las interfaces de usuario, con las cuales este -el usuario- ha de interactuar con el producto de software que vayamos a construir, para ir construyendo conceptualmente las demas capas de nuestra arquitectura de software.

Seguidamente un modelo de clases que se desprendera a partir de la discusion y analisis de los casos de uso, sera nuestro siguiente paso.

Dicho modelo de clases orientados al negocio del producto de software, que tenemos la mision de construir, estan relacionados en funcion a: herencia, asociacion, agregacion y otros mecanismos de relacion los cuales NO necesariamente deberian plasmarse tal cual en la estructura de datos final, ya en la Base de Datos.

Y he aqui la moraleja.

Ambas perspectivas tienen sus pros y contras, cada una de ellas validas desde sus respectivos puntos de vista.

Pero ambas perspectivas: Top Down y Bottom Up, se encuentran en ese punto. Aquel punto donde la conciliacion es el mejor fusible, para tener contentos a la mayoria, pero NO siempre la mejor solucion.

Para Bottom Up un Business Entity en terminos sencillos deberia ser tal cual una tabla que esta definida a nivel de Base de Datos. Tantas propiedades en cada Business Entity como columnas existan en la tabla correspondiente.

Por otro lado, Top Down propone algo diferente pues la relacion de una herencia o una agregacion a nivel de un modelo de clases de negocio NO se plasman tan facilmente a nivel de Base de Datos.

Menudo problema.

Monday, April 21, 2008

Web Service Software Factory

El Web Service Software Factory es una verdadera cochinada.

Más de cuatrocientos archivos que construye aquel bendito tool, de un modelo de NO mas de 20 tablas en mi base de datos, son prueba indubitable e insoslayable de la afirmación inicial.

Por cierto, recuerdo que tuve que renombrar a nivel del tool, todas la tablas e inclusive los campos de las mismas, para poder obtener un resultado relativamente decenten, en principio, a nivel de Business Entities.

Pero conforme vas haciendo cambios a nivel de la estructura de datos, te das con la amarga sorpresa, que esto trae como consecuencia que tengas que zambullirte en las cuchumil cuatrocientas clases creadas en el Data Access de tu solución.

Yo solo quiero hacer un UPDATE en un campo de una de mis tablillas. ¿Por que me complicas la vida?

¿Acaso no pensaron colocar un boton en el tool que diga algo asi como REFRESH?

En fin, esas son una de las razones por la que usar esta cochinada es una verdadera perdida de tiempo.

Nada como el BusinessLayer.Components y el BusinessLayer.Entities liberado hacer unos años atras, y que fue un golazo en su momento.

Hoy sin embargo, en los cuarteles de invierno, construyendose la version para LINQ aprovechando los lambda expression y clases anonimas para acelerar la construcción del Desarrollo de Software y que favorezca la estabilidad en dicha fase de producción.

Tan distante de las actuales realidades.

Thursday, March 27, 2008

Beta vs Release Visual Studio 2008

Cuando estas trabajando con el Visual Studio .NET 2008 version de evaluacion BETA, te sientes algo ofuzcado. Pero luego haces el cambio a la version RELEASE, la firme pe, la que se distribuye comercialmente y notaras ciertos cambios inmediatamente.

Uno de los cambios que se percibien con mayor claridad estan orientados a la velocidad con la que carga el Visual Studio .NET 2008 version comercial.

Haces click y ya tenemos el entorno de desarrollo abierto en el escritorio de trabajo. Sin tanto loading!

Y es que la version BETA se demora un siglo en abrirse y posteriormente cuando trabajas con la apertura de archivos en tiempo de diseño muestra cierto LAG.

Algo muy distinto en la version comercial.

Instala tu Visual Studio .NET 2008 ya!

Sunday, March 09, 2008

Page LoadControl UserControl OnInit

Cuando tecnicamente decides usar el Page.LoadControl( path ) para cargar dinamicamente en tiempo de ejecucion los UserControls definidos en tu web application, tienes que tener en mente ciertas caracteristicas que por cuestiones de diseño de ASP.NET son aplicables en este contexto.

Sucede que el evento OnInit del UserControl que se desea cargar dinamicamente no trabaja de la misma forma en la que se manifiesta cuando es cargado en tiempo de diseño.

En se caso, solo te queda realizar una llamada a un metodo que tu definiras en aquel UserControl donde estableceras explicitamente los EventHandlers de los Controles que alli este definidos.

Por ejemplo, si tuvieras un DataList, naturalmente es muy probable que necesites enlazarte al ItemDataBound de este DataList.

Algo que normalmente tendrias que definir en el OnInit del UserControl que contiene a este DataList.

Pero si este UserControl va a ser cargado dinamicamente en tiempo de ejecucion entonces te daras cuenta que algo no esta funcionando bien si lo haces de esa manera.

Por lo que corresponde realizar el enlace al ItemDataBound del DataList en el mismo metodo que es llamado por la pagina que contiene al UserControl para que en dicho metodo se realize dicho enlace.

Y ver que todo vuelve a la normalidad.

Tuesday, February 19, 2008

Planillas Electronicas SUNAT en Enero

La version 1.1 del software de Planillas Electronicas es una reverenda porqueria.

Por decir lo menos, merece aquel calificativo con todos los honores.

Alertas que no se ajustan a la realidad de los hechos. Lag en cada pantalla de la aplicacion. Y de pronto se congela tu aplicativo. Son algunas perlas del primer virus que debemos instalar en nuestra PC de acuerdo a Ley.

El reporte de alertas no brinda una interfaz amigable. Con toda seguridad en el primer año de la universidad hemos hecho mejores reporteadores, que aquel adefecio que vemos en este programita llamado planilla electronicas.

Todas las empresas del medio han tenido que moldearse a las caracteristicas que ha establecido SUNAT en el punto neuralgico de todo esto, con particular enfasis, conceptos remunerativos.

Sin embargo los conceptos remunerativos 2000 y posteriores no son posibles habilitar desde este programita. ¿Entonces para que diablos lo han puesto alli estos salvajes?

En fin, vergueza ajena nos embarga al ser obligado a usar este programilla de practicante de laboratorio.

Sunday, February 03, 2008

Sql Membership Provider

Cuando estas desarrollando un producto de software y decides que la authentication se realize a traves de Forms y NO a traves de otro mecanismo, por alguna circunstancia.

Debes evaluar si manejas los usuarios dentro del web.config. O decides manejar el provider de SQL, para este tipo de cosas.

Para lo segundo, debes ejecutar el aspnet_regsql que se encuentra en el folder correspondiente al .NET Framework 2.0 dentro de tu carpeta Windows.

Esta pequeña herramienta, te crea las tablas en la Base de Datos que tu hayas elegido utilizar para tu producto, con el prefijo aspnet para cada uno de los objetos de base de datos.

Lo curioso de todo esto es que, el tool, crea las tablas sin registros. Por ende, NO veras al user administrator por ningun lado.

Entonces debes crearlo manualmente para poder tener por lo menos al usuario: amo, dueño y señor de tu aplicativo, alli presente.

Ahora, cuando digo manualmente NO debe entenderse que hagas tu INSERT a nivel de Base de Datos.

Todo lo contrario, debes crear una pagina sencilla que permita utilizar el modelo de objetos que propone el .NET Framework dentro del namespace System.Web.Security, para crear el primer user y el primer role.

La clase Membership te brinda esta posibilidad a traves del metodo CreateUser y luego debes crear el role Administrators a traves de la clase Roles con el metodo CreateRole.

Finalmente asocias este role con tu primer user creado previamente, usando el metodo AddUserToRole de la clase Roles.

Pero aqui tenemos un pequeño detalle. Cada vez que realizes algun cambio en el web.config con respecto a la configuracion de tu provider, los usuarios creados hasta antes del cambio, NO podran ser visualizados luego.

Y tendras que llamar a esta pagina FirstStep para volver a crear el estado inicial de roles y usuarios.

Este ultimo detalle es una ladilla.

Pero tiene cierto fundamento logico. No te pelees con lo creado por los High Level Developers, esto ya esta disponible en el .NET Framework. Y se integra facilmente con todo el contexto del producto a nivel tecnico.

No te compliques la vida.

Row not found or changed

Uno de los exceptions que por lo general aparecen cuando estas trabajando con Linq to Sql, es el ChangeConflictException.

El mensaje tradicional correspondiente a este exception es: Row not found or changed.

Cuando recien estas construyendo el software. Muy probablemente te encuentres con este mensaje. Si no te calmas en encontrar la solucion, te podria sacar de tus casillas.

Lo que sucede es que generalmente la base de datos esta aun ajustandose, cambiando si un campo de la tabla permitira nulo o NO, por ejemplo. Si un tipo de dato BIT sera cambiado a un CHAR(1), por decir algo.

Y otras simpleces a nivel de base de datos.

Pero aquellos cambios, por la premura del tiempo o por alguna circunstancia, NO son plasmados tambien en el modelo que propone Linq To Sql, dentro de tu aplicativo.

Y he alli el origen del problema.

Cuando estas desarrollando software y te apoyas en Linq To Sql para facilitarte la construccion de los Business Entities, debes estar pendiente que la estructura de tablas de tu Base de Datos sincronize con las caracteristicas de los Business Entities asociada a cada tabla.

Al realizar una operacion de actualizacion o eliminacion contra la Base de Datos de un elemento en particular, Linq To Sql no construye la sentencia SQL en funcion a un WHERE mykeyfield = @mykeyfield

Linq To Sql realiza un WHERE en funcion al estado actual del registro previo al cambio.

Y si alguna caracteristica de tu Base de Datos NO esta sincronizada con el modelo de Linq To Sql, pues veras este mensajito constamente: Row not found or changed.

Por citar una ejemplo, que un campo en la base de datos haya sido cambio para NO permitir nulo, cuando antes si lo permitia. Pero sin embargo dicho cambio NO se realizo de la misma manera en el modelo de Linq To Sql, se entiende que para Linq To Sql aquel campo aun permite nulo.

Entonces al construir su WHERE, Linq To Sql, constuira una lista de campos para hacer el match del estado anterior del registro y con un myfieldchange IS NULL dentro de todos ellos.

En lugar de algo distinto al nosotros saber, que a nivel de Base de Datos, esto ya NO esta permitido.

En consecuencia, Linq To Sql NO puede encontrar el registro anterior, debido a que efectivamente este ya NO existe, bajo esas circunstancias.

La solución pasa por simplemente sincronizar la estructura de tu Base de Datos a nivel de campos con tu modelo de Linq To Sql.

Trabajo facil!

El arte de construir software

El desarrollo de software es un arte. El don de hacerlo simple y facil, pocos seres sobre la faz de la tierra pueden materializarlo.

La posibilidad de gestionar personas es una tarea algo distinta.

Hacerlos sentir a cada uno de ellos importantes. Coger sus buenas ideas y canalizarlas de alguna forma para que se sientan participes activos del producto a construir, es el reto.

Como Jefe de Proyectos tu requieres el cumplimiento de ciertas tareas, por parte de tus desarrolladores, lo mas ajustado al cronograma.

Pero existen ciertas tareas encomendadas que por su relativa complejidad requieren de tu apoyo.

Te encontraras con algunos que su idea, ciertamente, es buena. Solo debes ajustarla un tanto para que pueda engranar con el contexto. Recuerda, tu tienes la vision del bosque.

En otro casos, los más operativos aquella ideas no tienen mucho sustento. Se basan en un clasico COPY & PASTE luego un SEARCH & REPLACE para finalmente, tu al ver toda esa mazamorra, hacerle un SHIFT + DEL.

En fin, lo que sucede es que desarrollar software no es hacer CLICK & CLICK. O un nada ingenioso COPY & PASTE. Se requiere de cierto talento.

Dentro del mundo de los developers, ver algo distinto e interesantemente construido, por lo general se le califica, como "fumada", a primera vista. Pero luego se dan un tiempo para analizarlo y verlo detenidamente, y terminan por llamarlo: arte, en ciertos casos.

Y ese es el meollo del asunto desde un punto de vista lirico.

Cuando se requiere el cumplimiento de las tareas para ayer. Bienvenido tu COPY & PASTE, pero entonces saltara una pregunta. ¿Por que aceptaste una fecha asi?