Mostrando las entradas con la etiqueta Enterprise library. Mostrar todas las entradas
Mostrando las entradas con la etiqueta Enterprise library. Mostrar todas las entradas

Exception Handling y Logging con Enterprise Library 3.0

lunes, 11 de junio de 2007

En este artículo voy a mostrar como agregar un manejo simple de excepciones, y luego logging de éstas y otros eventos usando Enterprise Library 3.0, sin profundizar en todas las posibilidades que éstas librerías ofrecen.

Usaremos en este ejemplo los siguientes bloques de Enterprise Library 3.0:

  • Exception Handling Application Block
  • Logging Application Block (que registrará Excepciones recibidas por el bloque anterior, y otros mensajes de bitácora)
  • Data Application Block (para permitir al bloque anterior, Logging sobre una base de datos SQL)

(Es condición previa en el ejemplo siguiente, agregar referencias en nuestro proyecto a los assemblies correspondientes)

De la aplicación de ejemplo realizada en C#, nos interesa el siguiente bloque de código:


Vamos a trabajar sobre este método, que resulta crítico para nuestro sistema, por lo cual queremos una bitácora de su ejecución y resultado.



Exception Handling Application Block


Este bloque nos permite delegar el manejo de una excepción a una policy definida en archivos de configuración. En particular nos permitirá encapsular, reemplazar, absorber excepciones, o enviar éstas al Logging Application Block para registrarlas en una bitácora.

Para esto basta con modificar nuestro código de la siguiente manera:



Interceptamos cualquier tipo de Exception, y la manejamos con el método estático:

ExceptionPolicy.HandleException()

Éste recibe la excepción a ser manejada, el nombre de la policy a aplicar (a continuación vamos a definir esta política), y opcionalmente un parámetro out en el que se devuelve la excepción que reemplaza a la original (esto sucede cuando la policy utilizada decide que la excepción debe ser reemplazada o contenida dentro de una nueva), si la excepción no debe ser reemplaza este parámetro toma el valor null.

Este método devuelve true si la excepción (o la excepción que la reemplaza) debe ser relanzada.


Ahora sólo resta definir nuestra "TareasPolicy", para eso alcanza con editar el archivo de configuración (app.config, web.config, *.config) con la herramienta gráfica que incluye Enterprise Library (Enterprise Library Configuration Tool), con la cual resulta trivial lo siguiente:

  1. Agregar un bloque de configuración para Exception Handling, y dentro de éste crear una nueva policy con el nombre "TareasPolicy".
  2. Definir en esta policy para el tipo de excepción Exception (es decir para todas), un Logging Handler, y definimos para este Handler, que las excepciones produzcan entradas de Log de nivel "Error" (lógicamente), y con la categoría "Errores", vamos a ver que implica esto a continuación.

Dentro de una policy podemos definir también los siguientes Exception Handlers, que pueden utilizarse según el tipo de Exception lanzada:

Wrap Handler: Envuelve la excepción lanzada dentro de una nueva.
Replace Handler: Reemplaza la excepción con una nueva.
Logging Handler: Transfiere la excepción al Logging Application Block para poder registrarla en una bitácora.
Custom Handler: Permite manejar una excepción utilizando una clase definida en nuestra aplicación.
Fault Contract Exception Handler: Facilita el manejo de excepciones en aplicaciones SOA.



Logging and Instrumentation Application Block


Necesitamos ahora indicar como serán tratadas en este bloque las excepciones recibidas, pero antes es preciso definir las entidades más importantes en este bloque:

Trace Listener: Manejan los eventos registrándolos o emitiéndolos en distintos medios, son los siguientes:
  • Formatted EventLog: registra los eventos en el EventLog del sistema.
  • Flat File: simplemente almacena los eventos en un archivo de texto plano.
  • Rolling Flat File: utiliza un archivo de texto, que al alcanzar una antigüedad o támaño máximo se cierra y comienza uno nuevo.
  • Xml: en este caso el log generado es un documento xml, asimismo las entradas pueden contener un campo xml.
  • Email: envía notificaciones de eventos a traves de un servidor SMTP.
  • Msmq: utiliza Microsoft Message Query como destino de los eventos.
  • WMI: los eventos se manejan con Windows Management Instrumentation.
  • Database: Cuando recibe un evento, invoca un stored procedure con sus datos como parámetro. (Requiere el Data Access Block, para definir la base de datos a utilizar).
  • Custom: Si los anteriores no son suficientes, puede manejarse los eventos mediente una clase definida nuestra aplicación. Esto nos permitiría por ejemplo, mostrar un MessageBox, enviar el error con un POST HTTP, etc.
Formatter: Se encarga de serializar eventos, para facilitar su almacenamiento, son los siguientes:

  • Text Formatter
  • Binary Formatter
  • Xml Formatter
  • Custom Formatter
Event Sources: Representan fuentes de eventos, se les puede asociar uno o más Trace Listeners.
Pueden definirse segun categoría de los eventos, y están predifinidas adicionalmente las siguientes sources especiales:

  • All Events: Como su nombre lo indica, recibe todos los eventos de la aplicación.
  • Unprocessed category: Eventos de categorías no procesadas.
  • Logging Errors & Warnings: Recibe errores y advertencias producidos al registrar otros eventos (por ejemplo, caída del servidor del SQL, al intentar almacenar un evento en éste), permite una especie de "manotazo de ahogado", lo que hace apropiado asociar a esta fuente el Event Handler más "infalible", por ejemplo, Formatted EventLog.
Filters: Permiten filtrar eventos, según categoría, prioridad, o mediante clases personalizadas.


Ahora utilizamos una vez más la herramienta de edición de archivos de configuración para lo siguiente:

  1. Definir el bloque de configuración para el Logging Application Block.
  2. Definir el Category Source "Errores" como fue definido en el Exception Handling Block, este recibirá las Exceptions interceptadas por éste, y asociaremos a este un Database Handler, para crear nuestra bitácora en una base de datos.
  3. Crearemos (si no existe aún) la configuración para el Data Access Application Block, donde definiremos el connection string.
  4. Referenciar esta base de datos en nuestro Database Trace Listener, e indicar en éste el nombre del stored procedure que debe invocarse para agregar una entrada al log, y el stored procedure que se invoca inmediatemente después para indicar la categoría de ese evento (es por esto que el primer stored procedure, debe devolver el id de la entrada creada).
  5. Dado que nuestra conexión con la base de datos puede fallar (y queremos saber cuando!), agregamos un Formatted Event Log Trace Listener, y asociamos este al "Logging Errors & Warning" Special Source, para registrar en el EventLog los errores que ocurran al intentar usar la base de datos.

Por último aprovecharemos el Logging Application Block, para registrar también información adicional sobre la ejecución de nuestra tarea, para eso asociaremos nuestro Database Trace Listener al Special Source "All Events" (es posible definir un Trace Listener, o una categoría especial de eventos para este caso)

Ahora podemos modificar nuestro código C# de esta manera:


El método estático Logger.Write(), puede recibir también varios parametros adicionales como categoría, prioridad, severidad, etc.



Conclusiones

  • Las políticas de manejo de errores y logging, son totalmente independientes del código fuente: pueden ser establecidas de forma gráfica, en archivos de configuración, sin necesidad de recompilar la aplicación. Es decir, la modificación de estas políticas pueden ser delegada a un usuario administrador.
  • Por la misma razón que el punto anterior, al agregar estos bloques a una aplicación existente, el impacto sobre el código fuente es mínimo.
  • El manejo de Excepciones y Eventos de Log, es extensible definiendo "custom handlers", clases personalizadas que son invocadas para estas tareas.



Links


UPDATE 2009-06-12

Fe de erratas!, Como comenta Ariel (ver comentario en esta entrada), la forma correcta de relanzar una excepción es mediante throw; (de forma de mantener el stack trace), asi que en todos los bloques de codigo donde dice:

throw outEx ?? ex;

debería leerse:

if(outEx!=null)
throw outEx;
else
throw;
Leer más...

SQL Compact Edition

viernes, 18 de mayo de 2007

Presentación

SQL Compact Edition es un nuevo integrante de la familia SQL de Microsoft, y se trata de un motor SQL muy liviano y portable, pensado para utilizar pequeñas bases de datos en forma local.
Esta nuevo producto es la evolución de SQL Mobile Edition, el cual nos permitía tener un "mini" motor SQL en dispositivos portátiles (PocketPCs, Smart Phones), ahora extendido al resto de la sistemas operativos Windows (Tablet PCs y computadoras de escritorio).



Arquitectura

SQLCe, a diferencia de sus hermanos mayores, no se trata de un servicio de datos (tipicamente accesible de forma permanente, esperando consultas de aplicaciones cliente, locales o remotas), sino que se trata de una libreria (dll) que es refernciada por la aplicación cliente, es un motor "embebido" en la aplicación, optimizado para dispositivos de escritorio o portátiles.



Características Principales

  • SQLCe acepta sintaxis Transact-SQL, lo que lo vuelve facilmente escalable a sus hermanos mayores (SQL Express Edition, Standard Edition, etc). Aún así a la hora de portar código desde/hacia otro SQL Server es necesario tener en cuenta algunos puntos, por ejemplo: los tipos de datos en SQLCe, son un subconjunto de los disponibles para SQL Express Edition.
  • No pueden utilizarse Stored Procedures, esta limitación es clave a la hora de pensar en escalabilidad. Puede ser el punto que nos lleve a inclinarnos por SQL Express Edition. Más adelante, en una comparación entre SQLCe y SQL EE voy a resumir algunas razones por las que podría prescindirse de Stored Procedures.
  • Una base de datos SQLCe se almacena en un único archivo, lo que facilita la transferencia de bases de datos individuales.
  • SQLCe es un conjunto de librerías de alrededor de 2Mb, que pueden ser distribuídas con nuestra aplicación sin necesidad de registrar componentes, ni servicios, por lo tanto, no se necesitan privilegios de administrador durante la instalación, y los recursos de memoria y espacio en disco son mínimos.
  • Dado el tipo de dispositivos en los que SQLCe pretende funcionar (desde notebooks, pc's de escritorio a pocket pcs y smartphones), cuenta con características de seguridad, y protección contra errores (robo, perdida de energía) que son exclusivos para estas plataformas.
  • Herramientas para la sincronización de datos con SQL Server 2005

Veamos algunos puntos a tener en cuenta al decidir entre SQL Compact Edition y otras bases de datos locales.

SQL Compact Edition vs. XML o Archivos de Texto

  • Consultas, transacciones y manipulación de los datos
  • Encriptación nativa

SQL Compact Edition vs. Access o FoxPro

  • Integración con Visual Studio
  • Compatibilidad con el resto de la familia SQL Server

SQL Compact Edition vs. SQL Express Edition


SQL Compact Edition y SQL Express Edition se presentan como las dos opciones, ambas gratuitas, a la hora de implementar bases de datos locales en PC's de escritorio (Windows XP/Vista o Tablet PC), en cambio la opción es clara para dispostitivos móviles (SQLCe), y para bases de datos centrales, multiusuario (SQL Express).

  • Stored Procedures

Para los que estén acostumbrados a trabajar con bases de datos centrales, de gran escala, con múltiples usuarios accediendo concurrentemente con diversos privilegios, resulta inmediato basar la capa de datos en Stored Procedures, las históricas razones de esto son 3, voy a resumir porque estas razones podrían no tener tanto peso en un escenario muy distinto, como es una base de datos embebida, local y monousuario (escenario al que apunta SQL Ce).

  1. Rendimiento: Los stored procedures permiten ejecutar código de acceso a datos, optimizado para este uso. Sin embargo teniendo un solo usuario, sobre una base de datos local, implica que las consultas no llegarán con mayor concurrencia que los clicks de un usuario, por lo tanto (en lo que a performance se refiere) resulta aceptable codificar esta lógica procedural en la capa de datos de la aplicación.
  2. Abstracción: Acceder a los datos únicamente con stored procedures, es una forma de construir una capa de abstracción sobre éstos, sin embargo tanto el motor de SQLCe como las bases de datos pueden ser distribuídas y versionadas junto con la aplicación, y el beneficio de mantener esa abstracción ya no resulta tan evidente.
  3. Seguridad: Una vez más, los stored procedures permiten restringir el acceso a los datos, permitiendo únicamente ciertas operaciones sobre éstos, sin embargo la base de datos es distribuída con la aplicación y el usuario es único, en este escenario tienen más sentido otras medidas de seguridad, como encriptar la base de datos, e incluir en ésta únicamente el subconjunto de datos que el usuario local necesita.
  4. Dicho esto, por supuesto hay que evaluar la escalibilidad de nuestra aplicación, para evitar a toda costa verse en un futuro en la situación de traducir procedimientos C#/Vb.NET, a Transact-SQL.
  • Recursos, SQL Ce requiere de solo 2Mb en disco y un uso de memoria y procesador muy inferiores a SQL Express Edition, que al instalarse ocupa alrededor de 200Mb en disco, y al ser un servicio, se encuentra constantemente esperando ser invocado por una aplicación cliente (a pesar de estar preparado para "adormecerse" en períodos de inactividad)
  • Instalación, SQL Ce, puede distribuirse con nuestra aplicación, de manera que no requiera privilegios de administrador para instalarse y poder controlar su versionado. Alternativamente puede (como SQL Express) instalarse mediante un MSI, y recibir actualizaciones de Windows Update.
  • Almacenamiento, Ambos motores esta limitados a bases de datos de 4Gb, sin embargo las bases de datos de SQLCe estan contenidas en archivos individuales, "code-free" (sin código ejecutable, no sucede lo mismo con bases de datos de SQL Express), que pueden ser encriptados y protegidos con contraseña. Por lo tanto estos archivos pueden ser facilmente enviados, backupeados y asociados a una aplicación mediante una extensión de archivo particular.




Sql Ce con Enterprise Library 3.0

Una de las novedades en Enterprise Library 3.0 es la incorporación de clases para el manejo de SQL Compact Edition, bajo el nuevo namespace System.Data.SqlServerCe.

Una curiosidad es que el manejo de conexiones abiertas es distinto a los demás providers en Enterprise Library, por lo cual es aconsejable (para mantener la performance) utilizar transacciones para mantener una conexion abierta en operaciones en lote. Este comportamiento es explicado aqui:

http://www.codeplex.com/entlib/WorkItem/View.aspx?WorkItemId=9005

(fue reportado como bug, aunque la respuesta aclara que fue una decisión de diseño)

Links

http://www.microsoft.com/sql/editions/compact/default.mspx

http://www.microsoft.com/sql/editions/compact/sscecomparison.mspx

http://www.codeplex.com/entlib/WorkItem/View.aspx?WorkItemId=9005

Leer más...

Cryptography Application Block

Introducción

Este es un bloque de aplicación integrado en las versiones de Enterprise Library 2.0 y 3.0, basado en la criptografía, que intenta facilitarla y acercarla a los desarrolladores y sus aplicaciones, pudiendo utilizarlo para encriptar información, crear datos compactados y compararlos para verificar que la información no ah sido alterada.

Dentro de las principales características encontramos

  • Reduce los requerimientos para escribir código normalizado proveyendo implementaciones para solucionar problemas comunes de criptografía.
  • Ayuda a mantener prácticas consistentes de criptografía en la aplicación y la empresa.
  • Facilita la curva de aprendizaje de los desarrolladores usando un modelo de arquitectura consistente a través de varias áreas de funcionalidad que son provistas.
  • Provee implementaciones que pueden ser utilizadas para resolver los problemas básicos.
  • Es esténcil y soporta implementaciones adicionales de criptografía.


  • Escenarios comunes

    Los desarrolladores frecuentemente escriben aplicaciones que requieren encriptación y compactación de datos, para cumplir los requerimientos de seguridad de la organización. Tanto los datos que son creados y mantenidos por las aplicaciones como la información de configuración necesitan ser resguardadas. Adicionalmente las contraseñas que son usadas para acceder a la funcionalidad o datos de la aplicación requieren compactación. También favorece la abstracción del código de la aplicación respecto al de los proveedores de criptografía, permitiendo el cambio en la encriptación sin necesidad de modificaciones en el código del resto de la aplicación.
    Este bloque solo soporta algoritmos simétricos, que utilizan una misma llave para ambos procesos, pero no así los asimétricos, para los cuales el método de encriptación y desencriptación difieren en el código.

    Objetivos

  • Proveer una interfase simple e intuitiva para las funcionalidades más comúnmente requerida.
  • Encapsular la lógica de encriptación.
  • Lograr un modelo consistente y estandarizado para las tareas comunes relacionadas con la criptografía.
  • Asegurar un bloque de aplicación extensible.
  • Minimizar el impacto de las funciones criptográficas al resto de la aplicación.
  • Proveer un modelo basado en una “llave” que puede ser modificada por el usuario, para personalizar la encriptación.


  • Estructura y posibilidades

    El bloque separa las implementaciones de la encriptación y el resto de la aplicación permitiéndonos modificar uno sin alterar en nada el funcionamiento del otro. Dentro del mismo podemos encontrar con tres diferentes ámbitos.
  • La clase “Cryptographer” es una interfase que media entre el código de la aplicación y las funciones del “Cryptography Application Block”. El código del cliente llama a métodos estáticos de esta clase para crear compactaciones de información, compararlas, encriptar y desencriptar datos. Cada método estático llama a una clase de generación y pasa el código de configuración al constructor de la clase, con el mismo la clase determina que tipo de proveedor crear.
  • La clase “DpapiCryptographer” utiliza DPAPI (Data Protection API) para encriptar y desencriptar datos. DPAPI utiliza las credenciales de logueo para encriptar los datos, las mismas pueden ser de un usuario en una máquina o dominio, o de una computadora dentro de una red. En el caso de utilizar las credenciales de logueo de un usuario en una máquina, estas permiten que cualquier aplicación que el mismo usuario ejecute, pueda desencriptar toda información resguardada bajo la misma llave. Para no permitir esto se puede utilizar una clave o “entropy”. Hay métodos sobrecargados en la clase que permiten encriptar y desencriptar utilizado esta clave.
    Es importante remarcar que la necesidad de resguardar la seguridad de esta clave es tan necesaria como la encriptación de la información sensible.
  • La clase “SymmetricCryptographer” encapsula la implementación de la clase base abstracta “SymmetricAlgorithm”, la cual se encuentra dentro de “System.Security.Cryptography” en el .NET Framework. Esto significa que la clase en cuestión nos permite utilizar cualquier algoritmo simétrico de encriptación como por ejemplo el “Rijndael”. El bloque de aplicación utiliza DPAPI para encriptar y desencriptar la clave del algoritmo simétrico.


  • Conclusiones

    Este bloque de aplicación no intenta solucionar todos los casos en los cuales el resguardo de información y por ende la encriptación de los datos es necesaria, sino facilitar a los programadores novatos los primeros pasos, sin perder de vista que para determinadas aplicaciones, este bloque es lo suficientemente completo como para cumplir con todos los requisitos de seguridad de la misma. Con esto queremos concluir en que si bien el bloque es muy útil en muchos tipos de aplicaciones no hay que forzar la utilización del mismo en cualquier desarrollo, sino estudiar previamente si cumple con los requisitos que tenemos en ese momento.
    Leer más...