febrero 24, 2011

Manejo de excepciones en SQL Server

Dos formas de manejar los errores con SQL Server, sólo que con el uso de Try-Catch únicamente se puede implementar en versiones 2005 o superior y con el uso de GOTO desde la 2000.

Ambas formas funcionan, pero es más practica y segura (por si se omite validar alguna instruccion que provoque excepción) la que protege todo el bloque que es propenso a excepción.


---- Uso clásico con uso de marcadores y GOTO

Declare @Msj nvarchar(200)
--Comienza la transacción
BEGIN TRANSACTION

    --UPDATE 1
    --DELETE 1
    --Insert 1
    --para simular error
    Select 1/0
    --Verificar si hubo errores
    IF @@Error != 0
       GOTO ERROR_HANDLER

   

--Finalizar la Transacción
COMMIT TRANSACTION
print 'OK fin transacción'
SET NOCOUNT OFF
RETURN

--Manejador de Error.
ERROR_HANDLER:
ROLLBACK TRANSACTION
--Imprimir msj de error
set @Msj = 'Tenemos el error # ' + CONVERT(VARCHAR(10), Error_number()) + ' ' +
          Error_message() + ' en la linea: ' + convert(varchar(10), ERROR_LINE())
RAISERROR 13000 @Msj
RETURN


-----Uso con Try-Catch de SQL Server 2005 o superior
Declare @Msj nvarchar(200)
--Comienza la transacción
BEGIN TRANSACTION
BEGIN Try
    --UPDATE 1
    --DELETE 1
    --Insert 1
    --para simular error
    Select 1/0
COMMIT TRANSACTION
END Try

BEGIN Catch

    
    ROLLBACK TRANSACTION
    --Imprimir msj de error
       set @Msj = 'Tenemos el error # ' + CONVERT(VARCHAR(10), Error_number()) + ' ' +
           Error_message() + ' en la linea: ' + convert(varchar(10), ERROR_LINE())
      
       --PRINT @Msj
    Raiserror 13000  @Msj    

END Catch

febrero 16, 2011

Modelo Entidad Relación para Control de Acceso en las Aplicaciones (Roles por Aplicación)

Tenemos la necesidad de un modelo de base de datos que nos permita el control de acceso a los objetos de nuestra aplicacion, es así que tenemos una tabla de Aplicaciones o Sistemas que se compone de objetos, por ejemplo formas o paginas, botones etc. luego definimos los roles que tendrán acceso a nuestro sistema o aplicacion, por ejemplo Administradores, invitados (lectores) , operadores etc y éstos tendrán determinados derechos para Consultar, Insertar, Actualizar u Eliminar (CRUD), definidos los roles y sus derechos a los obejtos de nuestras aplicaciones, asociamos éstos a nuestros Usuarios, así que tenemos un sólo Usuario que podra accesar a las diferentes aplicaciones o sistemas que tengamos a través de la definición de un rol para cada aplicación.
A continuación les muestro el modelo E/R propuesto, espero les pueda servir!



Asi se veria un query con la información del rol que tiene un usuario vs. una aplicación, con el que podrimos hacer un objeto que este presente durante toda la session que tenga el usuario ante una aplicación:








febrero 15, 2011

Como manejar los bloqueos en SQL Server

Hace un tiempo tuve el problema de la concurrencia y como efecto de ésta tenia muchos bloqueos y quejas de los usuarios porque el aplicativo no les confirmaba sus operciones. Me puse a buscar en Internet de que hacer ya que los bloqueos no tenia forma de como evitarlos, pero necesitaba al menos hacer algo para manejarlos y miren este buen articulo que encontre:

http://www.codeproject.com/KB/database/SQLServer_deadlock.aspx

enero 30, 2011

Cómo enviar correo electrónico por código usando cuentas de GMail

Requeria enviar programaticamente emails,  pero no cuento con un servidor de email (SMTP), así que busque si se podia hacer a través de mi cuenta de GMAIL y encontré este fabuloso post con un ejemplo, lo probé y funciona a la perfección.

http://geeks.ms/blogs/jalarcon/archive/2007/06/23/c-243-mo-enviar-correo-electr-243-nico-por-c-243-digo-usando-cuentas-de-gmail.aspx

enero 29, 2011

Auditoria de instrucciones DDL

Con DDL Triggers apartir de SQL Server 2005 podemos auditar todos las operaciones de DDL a la BD

USE pruebas


--La tabla de auditoria
Create Table DDL_Auditoria(
Id int Not Null identity,
FechaEvento datetime not null,
TipoEvento SYSNAME not null,
UsuarioEvento SYSNAME not null,
NombreObjeto SYSNAME not null,
NombreObjetoObjetivo SYSNAME not null
)

--disparador
Create TRIGGER DDL_AuditoriaDML ON DATABASE FOR DDL_DATABASE_LEVEL_EVENTS
As

Declare @EV as XML
SET @EV = EVENTDATA()
INSERT INTO DDL_Auditoria
VALUES(
CAST(@EV.query('data(//PostTime)') as varchar(23)),
CAST(@EV.query('data(//EventType)') as Sysname),
CAST(@EV.query('data(//LoginName)') as Sysname),
CAST(@EV.query('data(//ObjectName)') as Sysname),
CAST(@EV.query('data(//TargetObjectName)') as Sysname)
)
go

--Probamos el disparador con 2 operaciones DDL y consultamos las entradas de auditoria en nuestra tabla
Create Table TablaNueva (Cve int)
go
Alter Table TablaNueva ADD Col2 int
go
Select * FROM DDL_Auditoria
go

DDL Triggers apartir de SQL Server 2005

En versiones anteriores sólo existian disparadores para operaciones DML para intrucciones INSERT, UPDATE y DELETE apartir de SQL Server 2005 es posible implementar disparadores para DDL

Por ejemplo:
USE pruebas

--Disparador que impediara modificar cualquier tabla de la BD.
Create Trigger DDL_1 ON DATABASE FOR ALTER_TABLE AS
     RAISERROR('No se puede alterar tablas en esta Base de Datos', 16, 1)
ROLLBACK
Go

--Para probar que no se puede alterar la tabla, intentaremos una intrucción DDL a la tabla.
Alter table T1 ADD COLUMNA3 Varchar(10)
go

enero 17, 2011

Patrón de diseño: Estrategia

Utilizaremos el patrón stretegy porque se requiere implementar un mecanismo dinámico para el calculo de impuesto de acuerdo al país a donde se va a facturar, por ejemplo Europa, EE.UU y  México y quizás otros paises más.

Proposito: De comportamiento
Alcance: Objeto
A continuación el diagrama de clases que representa a este patrón.
Ahora el diagrama de clases del calculo de impuestos de acuerdo al país
El código en C#
La clase contexto:

La interface que de acuerdo al tipo de objeto selecciona la clase concreta para realizar el calculo del impuesto.


las clases concretas, que implementan a la interface con el calculo del impuesto correspondiente a cada país

y finalmente el cliente

Asi si en el futuro de factura a otro país, sólo tenemos que implementar la interface con una clase concreta que realice el calculo correspondiente.
http://es.wikipedia.org/wiki/Strategy_(patr%C3%B3n_de_dise%C3%B1o)

Patrón de diseño: Método Plantilla

Utilizaremos el patrón Template Method porque queremos crear una clase que nos permita trabajar cierta funcionalidad independientemente del manjeador de base de datos, acontinuación veremos su representación en el diagrama de clases:

Ahora el diagrama de clases de lo que nosotros queremos (ejecución de operaciones independientes del manejador de base datos).


Y ahora el código en C#

Esta es la clase que contiene el método plantilla. Observemos que los métodos que tienen que ver con el manejador de base de datos se han definido abstractos (sin implementar) pues estos deberán ser implementados por cada clase que represente al manejador de base de datos que queremos trabajar.


Las clases concretas que se casan con el manejador de Base de Datos
Otra clase concreta que implementa a la clase ConectividadBD, ahora para Oracle
Y el código cliente:
Y así si queremos utilizar Informix, DB2 y los que sean.

enero 16, 2011

Herencia entre Interfaces

Las interfaces no pueden heredar de clases, pero si de otras interfaces. En la siguiente imagen vemos como IVehiculoVolador hereda de IVehiculo, porque un VehiculoVolador también es un Vehiculo y al implementar la interface IVehiculoVolador tenemos que implementar las dos interfaces.



Ahora el mismo diagrama, pero con los métodos implementados de las interfaces que utilizan:

enero 14, 2011

Invocar al Constructor de la clase Base en C#

Tenemos una clase que hereda de otra y sabemos que los constructores no son heredados, entonces podemos desde la clase que hereda invocar al constructor de la clase base, en este caso para no volver a escribirlo o quizas en su cuerpo agregar alguna otra inicialización.

Lista de parámetros dinámica a una función C#

Requerimos hacer una función que reciba un número de parámetros desconcido desde 1 hasta N valores para tratarlos a todos.

//Los parámetros dinámicos se definene en la firma del método como un arreglo sin tamaño.
public static int Suma(params int[] argumentosN)
{
    int total = 0;//el acumulador
    for (int i = 0; i < argumentosN.Length; i++){
       total += argumentosN[i];
     }
     return total;
}


Al llamar a la funcion pasamos el # de parametros que queramos, en este caso siempre los sumara todos

Console.WriteLine("valor : " + Suma (4,5,5,5,6));
Console.WriteLine("valor : " + Suma (4,5,5,5,6,3,4,5,33,45,2,3,44,5,1,12,4));

Algunas Consideraciones en el Uso de las Variables: Locales, de Instancia y Estáticas en .NET


Así, las variables locales siempre deberan ser inicializadas antes de utilizarlas sino el compilador marcará un error. Los campos o variables de clase sino so inicializadas, éstas serán inicialzadas a sus valores defaul correspondientes, los tipo númericos a cero y los tipos de datos referencia a null para ello tenga presente el uso de constructores.

enero 13, 2011

Clasificación de tamaño de los proyectos en el desarrollo sistemas

Comenzaremos por la definición de proyecto que por ahi encontré.

Proyecto: Conjunto o secuencia de actividades que se desarrollan durante un tiempo por un equipo de personas para obtener un resultado u objetivo concreto. Así un proyecto siempre tendrá:

* Un objetivo concreto por alcanzar
* Una linea de tiempo con un principio y un final
* Un equipo de personas
* Recursos limitados (dinero, equipos, licencias...)

Y cómo podemos clasificar a los proyectos de software de acuerdo a su tamaño? bueno considero que n función de dos factores: tiempo y número de personas:

* Chicos: tienen una duración menor o igual a 6 meses con la participación de un equipo de personas de 1-5

* Medianos: tienen una duración mayor a 6 meses y menor o igual 36 meses con la participación de un equipo de personas de 5 a 15

* Grandes: tienen una duración de más de 36 meses y con un equipo de personas mayor a 15

¿Cuáles son hoy las habilidades necesarias para la construcción del Software?

* Análisis de Requisitos
* Análisis y Diseño Orientado a Objetos
* Programación Orientada a Objetos
* Ingenieria de usabilidad
* Diseño de Interfaces de usuario
* Diseño de Base de Datos
(Referencia: UML y Patrones. Craig Larman)

enero 09, 2011

Múltiples referencias al mismo objeto (Referencias entre objetos)

Definción de referencia: Una referencia es un valor en tiempo de ejecución que está: o vacío o conectado.

Caso ejemplo:
Tenemos una clase que nos permite almacenar libros, es así que un libro se compone de la siguiente información:


-Titulo
-Año de publicación
-No paginas
-Autor
-Fecha Nacimiento
-Pais de Origen


De tal modo que cuando necesitamos crear más de un objeto Libro para los cuales se trata del mismo autor se veria de la siguiente forma:




Asi que por ello es la referencia entre objetos, es decir; en el objeto Libro habrá un apuntador que referncia al objeto Autor:






En el Diagrama de Clases lo podemos ver en la navegación, en donde la clase Libro tiene un apuntador a la case Autor:


Y en la implemantación en C# como una aplicación de consola:

using System;
class Libro
{
public string Titulo;
public Int16 AñoPublicacion;
public Int16 NoPaginas;
public Autor AutorLibro; //esta es la variable para hacer la refencia la objeto Autor
}

using System;
class Autor
{
public string Nombre;
public string FechaNacimiento;
public string PaisOrigen;
}

Y el programa cliente que hace uso de las clases y las relaciona através de referencias entre objetos:

using System;
class Program
{
static void Main(string[] args)
{
//creamos 2 libros que tienen mismo autor
Libro Libro1 = new Libro();
Libro1.Titulo = "Ensayo de la ceguera";
Libro1.AñoPublicacion = 1998;
Libro1.NoPaginas = 234;

Libro Libro2 = new Libro();
Libro2.Titulo = "El Evangelio Segun Jesucristo";
Libro2.AñoPublicacion = 1992;
Libro2.NoPaginas = 334;

//genereamos el autor
//Cuando se realiza una instancia de una clase (mediante new) se reserva en la memoria un espacio
//para un conjunto de datos como el que definen los atributos de la clase que se indica en la instanciación.
//A este conjunto de variables se le denomina variables de instancia.
Autor Autorlibro = new Autor();
Autorlibro.Nombre = "José Saramago";
Autorlibro.FechaNacimiento = "22/07/1948";
Autorlibro.PaisOrigen = "Portugal";

//Los 2 libros los escribió el mismo autor de tal modo que la referencia es al mismo objeto autor.
//las variables AutorLibro de cada Libro apuntan ambas al mismo Autor que es la variable de instancia creada arriba con new.
Libro1.AutorLibro = Autorlibro;
Libro2.AutorLibro = Autorlibro;

//Ahora vamos a imprimir los libros con su respectivo autor para identificar que se trata del mismo.
Console.WriteLine("Impresión del libro 1:");
Console.WriteLine("Titulo: " + Libro1.Titulo);
Console.WriteLine("Año de Publicación: " + Libro1.AñoPublicacion);
//ahora exponemos los datos del autor que apuntan desde el objeto libro al objeto autor.
Console.WriteLine("Autor : " + Libro1.AutorLibro.Nombre);
Console.WriteLine("Fecha de Nacimiento : " + Libro1.AutorLibro.FechaNacimiento);
Console.WriteLine("Pais de Origen: : " + Libro1.AutorLibro.PaisOrigen);

Console.WriteLine("");
Console.WriteLine("Impresión del libro 2:");
Console.WriteLine("Titulo: " + Libro2.Titulo);
Console.WriteLine("Año de Publicación: " + Libro2.AñoPublicacion);
//ahora exponemos los datos del autor que apuntan desde el objeto libro al objeto autor.
Console.WriteLine("Autor : " + Libro2.AutorLibro.Nombre);
Console.WriteLine("Fecha de Nacimiento : " + Libro2.AutorLibro.FechaNacimiento);
Console.WriteLine("Pais de Origen: : " + Libro2.AutorLibro.PaisOrigen);
Console.WriteLine("");
Console.WriteLine("Enter para terminar");
Console.ReadLine();//espera un Enter para continuar.
}
}
La salida:


Y asi, si el mismo autor tiene 100 libros todos los objetos Libro tendrán una refencia al mimo objeto Autor. Y este mismo esquema aplica para muchos casos por ejemplo tenemos muchas Facturas expedidas al mismo Cliente, no tenderemos un objeto Cliente por cada objeto Factura, habrá muchas Facturas todas apuntando al mismo Cliente.

enero 04, 2011

Cursores FAST-FORWARD en SQL Server

If you have no choice but to use a server-side cursor in your application, try to use a FORWARD-ONLY or FAST-FORWARD, READ-ONLY cursor. When working with unidirectional, read-only data, use the FAST_FORWARD option instead of the FORWARD_ONLY option, as it has some internal performance optimizations to speed performance. This type of cursor produces the least amount of overhead on SQL Server.

http://www.sql-server-performance.com/tips/cursors_p1.aspx


EJEMPLO de uso:
--Declaramos las variables
Declare @cod as int
Declare CURSOR1 cursor FAST_FORWARD for
select Valor from tabla1
Open CURSOR1

-- Avanzamos un registro y cargamos en las variables los valores encontrados en el primer registro
fetch next from CURSOR1
into @cod
while @@fetch_status = 0
Begin
--intruccion: la necesidad de implementar el cursor.
print convert(varchar(10), @cod)

-- Avanzamos otro registro
fetch next from CURSOR1
into @cod
End

-- cerramos el cursor
close CURSOR1
deallocate CURSOR1

Store Procedure con lecturas sucias

Ventajas: no hay bloqueos.

Desventajas: los select no obtienen valores al 100% vs lo que inserta, actualiza o elimina la concurrencia.


SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE dbo.spuX
AS
BEGIN
SET NOCOUNT ON;
--especiifcacion de nivel de aislamiento (equivalente a usar NoLock
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT 1
END
GO

¿Cuando usar Cursores?

Los cursores son buenos cuando estamos hablando de menos de 300 registros, las tablas temporales seria la mejor opción, pero si sabemos que la tabal temporal podria tener unos 1000 registros mejor utilecemos una variable de tipo table en lugar de la tabla temporal que se crea en el disco en la bd de Tempdb.

Los cursores reservan recursos en el servidor, como por ejemplo locks, packages,
procesos, almacenamiento temporal, etc. Por ejemplo, Microsoft SQL Server implementa los cursores creando una tabla temporal y rellenándola con los datos de la consulta.
Si un cursor no se cierra de manera correcta, el recurso no será liberado hasta que la sesión SQL (conexión) sea cerrada. Este desperdicio de recursos en el servidor puede llevar no sólo a una degradación del rendimiento, sino también a fallos más graves.

Variables Tabla (CursorLess) SQL Server

Un ejemplo de utilizar variables tabla en SQL Server
http://www.eggheadcafe.com/articles/20010823.asp

Algunas ventajas: son que todo se trabaja en memoria no hay I/O como es el caso de tablas temporal.

USE NORTHWIND
--1. Declaracion de la variable tabla
declare @SpecialCustomers TABLE (
CustomerID nchar (5) NOT NULL ,
OrderID int NOT NULL ,
ShipVia int NOT NULL,
Freight money NOT NULL)

--2. poblamos la variable tabla con la informacion de la tabla Orders
insert into @SPecialCustomers select CustomerID, OrderID, ShipVia, Freight
from dbo.Orders where ShipVia =1 AND Freight >50.25

--3. Actualizamos datos con el uso de la informacion en la variable tabla
UPDATE ORDERS SET ShipVia=4, Freight =21.00
where ORDERS.OrderID IN (SELECT ORDERID FROM @SpecialCustomers)es o cursores.