SQLTableHistory utilidad para hacerle auditoria a tus tablas

SQLTableHistory es una utilidad que hicimos junto a un compañero que nos permite llevar un rastro de auditoria de tablas especificas que podemos seleccionar desde la aplicacion, mantiendo asi un registro de cada accion(insertar, actualizar, eliminar) que involucre las tablas que se le quiera hacer la auditoria.

Requerimientos

  • .Net Framework 3.5
  • Sql Server 2000-2005

Arquitectura

La aplicacion consta de de una sola tabla llamada AUDIT donde guarda cada uno de los registros de las tablas, guardando asi el nombre de la tabla, nombre de la columna que fue afectada el valor anterior y el valor nuevo de la columna, el usuario de la transaccion, fecha y  asi tambien el tipo de transaccion que fue realizada(insertar, actualizar, eliminar).

Para ser posible esto, la utilidad nos crea tres triggers por cada una de las tablas, uno para insertar, actualizar e eliminar.

tableaudit

Script:

Tabla Audit:

/****** Object:  Default [DF_Audit_Date]    Script Date: 02/22/2008 19:27:40 ******/
IF  EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[DF_Audit_Date]’) AND type = ‘D’)
BEGIN
ALTER TABLE [dbo].[Audit] DROP CONSTRAINT [DF_Audit_Date]

END
GO
/****** Object:  Table [dbo].[Audit]    Script Date: 02/22/2008 19:27:40 ******/
IF  EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[Audit]’) AND OBJECTPROPERTY(id, N’IsUserTable’) = 1)
DROP TABLE [dbo].[Audit]
GO
/****** Object:  Table [dbo].[Audit]    Script Date: 02/22/2008 19:27:40 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[Audit]’) AND OBJECTPROPERTY(id, N’IsUserTable’) = 1)
BEGIN
CREATE TABLE [dbo].[Audit](
    [AuditID] [int] IDENTITY(1,1) NOT NULL,
    [Table] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [Column] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [OldValue] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [NewValue] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [UserID] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [Date] [datetime] NOT NULL,
    [Type] [int] NOT NULL,
CONSTRAINT [PK_Audit] PRIMARY KEY CLUSTERED
(
    [AuditID] ASC
)
)
END
GO
/****** Object:  Default [DF_Audit_Date]    Script Date: 02/22/2008 19:27:40 ******/
IF Not EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[DF_Audit_Date]’) AND type = ‘D’)
BEGIN
ALTER TABLE [dbo].[Audit] ADD  CONSTRAINT [DF_Audit_Date]  DEFAULT (getdate()) FOR [Date]

END
GO

 

Tabla AuditType:

/****** Object:  Table [dbo].[AuditType]    Script Date: 02/22/2008 19:35:13 ******/
IF  EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[AuditType]’) AND OBJECTPROPERTY(id, N’IsUserTable’) = 1)
DROP TABLE [dbo].[AuditType]
GO
/****** Object:  Table [dbo].[AuditType]    Script Date: 02/22/2008 19:35:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[AuditType]’) AND OBJECTPROPERTY(id, N’IsUserTable’) = 1)
BEGIN
CREATE TABLE [dbo].[AuditType](
    [AuditTypeID] [int] NOT NULL,
    [Name] [varchar](20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
CONSTRAINT [PK_AuditType] PRIMARY KEY CLUSTERED
(
    [AuditTypeID] ASC
)
)
END
GO

Y debemos tener estos tres valores por default en nuestra base de datos:
INSERT [dbo].[AuditType] ([AuditTypeID], [Name]) VALUES (1, convert(text, N’Agregar’ collate SQL_Latin1_General_CP1_CI_AS))
INSERT [dbo].[AuditType] ([AuditTypeID], [Name]) VALUES (2, convert(text, N’Remover’ collate SQL_Latin1_General_CP1_CI_AS))
INSERT [dbo].[AuditType] ([AuditTypeID], [Name]) VALUES (3, convert(text, N’Modificar’ collate SQL_Latin1_General_CP1_CI_AS))

Clases

Usando Linq to SQL y a la vez el Designer, tenemos las siguientes clases:

clasese

Donde:

SysTable: es la clase que contiene todas las tablas de nuestra base de datos seleccionada, se conecta a la tabla sys.tables

Table: clase que contiene el schema de las tablas, se conecta a la tabla INFORMATION_SCHEMA.TABLES

Trigger: es la clase que contiene los triggers de la base de datos, se usa la tabla del sistema sys.triggers

Column: clase que contiene el schema de las columnas de cada tabla de nuestra base de datos, para obtener esto se usa la tabla del sistema INFORMATION_SCHEMA.COLUMNS

Si se fijan para todo esto usamos tablas del sistema, ya que estas nos pueden proveer el schema de las tablas y poder asi crear los triggers de una manera dinamica.

Deben configurar el archivo app.config en la cadena de conexion y espeficiar el connectionstring correspondiente a su base de datos… en un futuro lo pondre para que se pueda hacer de manera mas dinamica.

Si les interesa pueden descargar el codigo fuente y asi poder echarle una miradita al codigo.

Preview de la utilidad:

app

Espero que les sea de utilidad.

Instalar Windows Vista SP1 desde Windows Update

Con la llegada de Windows Vista Service pack microsoft corregira muchos de los errores reportados por un gran numero de usuarios (entre los que me incluyo), tales como:

  • Escalabilidad
  • Seguridad
  • Rendimiento
  • Soporte de nuevos estandares
  • otros

Para mas detalle pueden ver la entrada que hizo Joshua Saenz en este enlace. Pero para tener todas estas nuevas bondades que nos trae nuestro amigo Vista y poder descargarlo desde Windows update tenemos que esperar hasta mediados de marzo.

Si tienes la fiebre como yo de poder tener el Service pack 1 instalado desde ya, hemos visto esta entrada en el blog The .Net Aficionado en la cual se publico una porcion de codigo que nos habilita la descarga via Windows Update del Service pack 1. Puedes copiar y pegar este codigo en un archivo .cmd y correrlo (logicamente si lo corres es bajo riesgo propio)

 

@echo off

reg delete HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionWindowsUpdateVistaSp1 /f > NUL 2>&1
reg delete HKEY_LOCAL_MACHINESOFTWAREWow6432NodeMicrosoftWindowsCurrentVersionWindowsUpdateVistaSP1 /f > NUL 2>&1

reg add HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionWindowsUpdateVistaSp1 /v Beta1 /t REG_SZ /d dcf99ef8-d784-414e-b411-81a910d2761d /f
IF NOT %errorlevel% == 0 ( goto ERROR)

:SUCCESS
@echo.
echo ===========================================================
echo  Windows Vista SP1 registry key has been set successfully.
echo  Please check for updates in Windows Update.
echo ===========================================================
@echo.
goto END

:ERROR
@echo.
echo ===========================================================
echo  FAILED to set Windows Vista SP1 registry keys.
echo  Please run this script by right clicking and selecting
echo  "Run as Administrator".
echo ===========================================================
@echo.
goto END

:END
pause

Espero que les sea de utilidad.

Microsoft ofrece $44.600 millones de dólares por Yahoo

Luego de la presentación sobre LINQ, despertamos y lo primero que vemos es una tremenda noticia, microsoft ofrece por yahoo la modica suma de $44.600 millones de dólares. lo referente a 31 dólares por acción, un 62% del valor que tenían los títulos a día de ayer.

Es una tremenda oferta ya que todos hemos podido ver como en los ultimos meses las acciones de yahoo se han desplomado, esta oferta ha provocado que las acciones de yahoo suban en mas de un 59%.

Creo la posible fusion entre yahoo y microsoft, provocaria un fuerte binomio que atentaria con la supremacia total que tiene google en la red.

Esperemos a ver como se desenvuelve esta noticia.