sábado, 23 de octubre de 2010

Implementando transacciones en procedimientos almacenados

En la siguiente entrada vamos elaborar un procedimiento almacenado que contiene una transacción la cual revertirá los cambios realizados por todas las operaciones que tengan lugar dentro del procedimiento en caso de presentarse algún fallo.

Imagenemos por un momento que tenemos un formulario de registro de empleados para una empresa en la cual se captura la información básica del empleado y además el cargo desempeñado dentro de la organización.

Para este caso hipotético se tiene una base de datos con la siguiente estructura:
  • Una tabla Persona que contiene la información básica del empleado y un campo IdPersona que es auto numérico.
  • Una tabla Cargo que almacena el listado de cargos que existen en la empresa.
  • Una tabla Cargo_Empresa en la cual se vincula a un empleado el cargo que desempeñado en la empresa (Para este ejemplo hipotético imaginemos que una persona puede tener solo un cargo pero que por cuestiones a analizar en esta entrada se ha ubicado en una tabla externa). El modelo según lo anterior seria el siguiente.


Para poder capturar esta información vamos a hacer uso de los procedimientos almacenados (Stored Procedure). Para crear el procedimiento seleccionaremos la opción Nuevo Procedimiento Almacenado el cual esta ubicado en la seccion Programación >> Procedimientos almacenados dentro de la base de datos DB_Ejemplo tal como se aprecia en la siguiente imagen.



En el procedimiento la secuencia es operaciones es :
  1. Recibir los parametros de la tabla Persona.
  2. Recibir el IdCargo que tiene asignado el empleado en la organización.
  3. Registrar el empleado en la tabla Persona.
  4. Obtener el IdPersona, el cual es un campo numérico autogenerado (Identity) durante la inserción.
  5. Ingresar en la tabla Cargo_Persona el IdCargo recibido y el IdPersona generado en la operación 3.
Según esta secuencia de operaciones la estructura del procedimiento es la siguiente:





Después de ejecutar el procedimiento ingresaremos unos registro en la tabla cargos. Para evidenciar la problematica generada por no implementar procedimientos almacenados en aplicaciones donde tiene lugar la realización de multiples operaciones del tipo UPDATE, INSERT y/o DELETE, ejecutaremos el procedimiento RegistrarPersona pasándole un valor erróneo (que no exite en la tabla Cargo) para el parametro IdCargo. Recordemos que dentro de la tabla Cargo_Persona existe un campo llamado IdCargo y que es llave foránea de la tabla Cargo, por lo cual existe una integridad referencial entre estas.

Después de ejecutar la instrucción de invocación (Véase archivo Exec RegistarPersona.sql) para nuestro procedimiento sin transacción tendremos el siguiente error.




Si examinamos la tabla Persona veremos que hay un registro pero en la tabla Cargo_Persona no hay , esto es debido que no se agruparon las operaciones, en este caso del tipo INSERT , bajo una transacción, esta problematica sin duda generará muchos inconvenientes de integridad en nuestro sistema si no se tienen en cuenta la momento del desarrollo de la aplicación.

Para corregir esto se agregará un bloque TRANSACTION dentro de un TRY-CATCH el cual en caso de éxito ejecutará la instrucción COMMIT TRANSACTION guardando todo la información el la base de datos y en caso de fallo ejecutará la instrucción ROLLBACK TRANSACTION la cual revertirá todas aquellas operaciones ejecutadas previamente y que esten ubicadas dentro del bloque TRY. El código de nuestro nuevo procedimiento haciendo uso de las transacciones será el siguiente.




Después de ejecutar el procedimiento volvemos a invocar las instruciones contenidas en el archivo Exec RegistarPersona.sql pasando nuevamente un valor erróneo para el parámetro IdCargo , el resultado es el siguiente.



Como se aprecia en el anterior gráfico la operación nuevamente lanzo un error de integridad referencial pero a diferencia el primer procedimiento planteando veremos que no se han guardado registros en la tabla Persona o Cargo_Persona, garantizando de esta manera la atomiciadad de las operaciones al poder manejar múltiples instrucciones y ser administradas como una sola operación.


Descripción de los archivos :
  • Script Base datos DB_Ejemplo.sql :Contiene el esquema de la base de datos y lo s registros de la tabla Cargo.
  • Exec RegistarPersona.sql : Contiene las instrucciones para invocar el procedimiento almacenado.
  • SP RegistarPersona Con Transaccion.sql: Contiene el procedimento almacenado sin la transacción.
  • SP RegistarPersona Sin Transaccion.sql : Contiene el procedimiento con la transacción implementada.

Descargar el código fuente de la aplicación de clic aquí.

jueves, 21 de octubre de 2010

Creando un control de servidor personalizado en ASP.NET

En el siguiente tutorial aprenderemos a crear un control de servidor personalizado de ASP.NET. Para este ejemplo crearemos un proyecto de Biblioteca de clases en el que se agregará un clase que heradará de la clase Label la cual esta contenida en espacio de nombres System.Web.UI.WebControls. Para poder referenciar la clase Label desde este espacio de nombres es necesario importar el ensamblado System.Web, para ello de clic derecho sobre el proyecto dentro del explorador de solucciones y escoga la opcion Agregar referencia. Una vez seleccionada esta opción se presentará una ventana emergente donde buscaremos la referencia requeridad. Vease las siguientes imagenes.







Despues de agregar la referencia crearemos una clase llamada CLabel en la cual se sobreescribirá unos metodos para asi poder personalizar la apariencia que tendra el control. Una vez agregado el codigo personalizado la apariencia de nuestra clases sera similar a la siguiente imagen.


Con estos pasos se finaliza la creación del control personalizado de servidor. Para implementar este control se requiere agregar un nuevo sitio web en la misma solución (si lo desea solo referencie la ddl como se verá mas adelante) para ello de dirijase a la opccion Archivo >> Agregar Nuevo Sitio Web y cree el sitio web. Con esto tendremos dos proyecto en nuestra solución tal como se aprecia en la siguiente imagen.



Despues de este paso debemos referenciar el control creado dentro del sitio web, para ello daremos clic derecho sobre el sitio web y agregaremos la referencia hacia el proyecto que contiene la Biblioteca de clases tal como se aprecia en la siguiente imagen.




Con esto aseguremos que cada modificación realizada en el control se vera reflejada en sitio web. Para asegurar de que la referencia fue creada satisfactoriamente basa con examinar en el Explorador de soluciones la carpeta Bin, en esta carpea deberá estar el componente (dll del control) . Nuestra estructura de directorio se verá como la siguiente imagen.




Ahora solo falta agregar nuestro control a la barra de herramientas de Visual Studio, para ello agregaremos una nueva ficha a la cual llamaremos ControlLabel y despues le agregaremos los compomentes contenidos (En nuestro caso la Biblioteca de clases solo contiene un control pero puede contener varios) en la dll dando clic derecho y seleccionado la opción Elegir elementos tal como se aprecia en la imagen.



En el cuadro que emerge despues de seleccionar la opción Elegir elementos procederemos referenciar la dll ubicada dentro de la carpeta Bin de nuestro proyecto web. Una vez seleccionada prodremos ubicar el control CLabel en el cuadro de herramientas y trabajar con el como si trabajaramos con cualquier tipo de control de sevidor de los que proporciona ASP.NET. La imagen de la anterior accion se muestra a continuación.


Cabe aclarar que cuando en la misma solución se encuentra el compomente (CLabel) y el sitio web, Visual Studio carga automaticamente el componente a la barra de herramientas, en ese caso el paso anterior podria omitirse. Para mayor entendimiento vea la siguiente imagen.


Ahora para finalizar la implementación del control de servidor personalizado procedemos a incluir el control CLabel dentro de la página, para ello arrastraremos el control hasta la página y le asignaremos un valor. Para mayor comprensión vea la siguiente imagen.



Y para finalizar dejamos la apariencia de control ejecutandose.





Para descargar el codigo empleado en esta entrada de clic aquí.