martes, 4 de enero de 2011

OBTENIENDO EL LOG DE LINQ to SQL UTILIZANDO EL DATACONTEXT

 

Hola…

Me he encontrado en una situación en la que requiero registrar el log de todas las operaciones realizadas en una aplicación

Para dar solución a dicho requerimiento lo que hice fue registrar todas las operaciones SQL realizadas sobre la base de datos.

Teniendo en cuenta que la aplicación se encuentra en ASP.NET y la capa de datos la estoy trabajando con LINQ to SQL opté por obetener las transacciones realizadas a través del DataContext.

A continuación explico como realicé dicho proceso:

1. Requerimiento:

Registrar el log de todas las transacciones realizadas en la aplicación

2. Escenario:

Aplicación en ASP.NET utilizando LINQ to SQL como capa de datos.

A través del editor del LinqToSQL cree el diagrama y lo llamé bdRemisiones.dbml

image 

3. Solución:

Teniento en cuenta que a través del diseñador se crean automáticamente las clases que me permiten abstraer el modelo de la base de datos y entre ellas una llamada bdRemisionesDataContext que se encarga de conectar a la base de datos realizar las respectivas actualizaciones (para ver como se hace recomiendo: tutorial-de-linq-to-sql)

La clase creada por el diseñador es una clase parcial, lo que me permite adicionar métodos y propiedades desde otro archivo (OJO: es importante que sea en otro archivo, por que si se hace una modificación al modelo, los cambios se pueden perder)

Ahora, simplemente lo que hice fue crear en un archivo nuevo de clase, crear la clase parcial que me permite obtener el log de las transacciones SQL realizadas por el bdRemisionesDataContext asi:

Partial Public Class bdRemisionesDataContext
Inherits System.Data.Linq.DataContext

End Class



Luego definí un strinWriter para almacenar el contenido del log:

Dim writer As New System.IO.StringWriter()





 


despues, con el fin de que al crear un nuevo bdRemisionesdatacontext automaticamente se incie el registro del log creé el método onCreated() en el cual asigno el log del datacontext (ver  Datacontex.Log)


 

 Private Sub OnCreated()
MyBase.Log = writer
End Sub



Luego creo un método que me retorna un string con el log de las opreaciones realizadas por dicho datacontext:


 

    Public Function GetLogStr() As String
Dim lg As String
MyBase.Log = writer
lg = writer.ToString()
Return lg
End Function

el código completo se ve asi:

Partial Public Class bdRemisionesDataContext
Inherits System.Data.Linq.DataContext

Dim writer As New System.IO.StringWriter()

Private Sub OnCreated()
MyBase.Log = writer
End Sub

Public Function GetLogStr() As String
Dim lg As String
MyBase.Log = writer
lg = writer.ToString()
Return lg
End Function

End Class

Ahora para utilizar el log creado simplemente creo un objeto el bdRemisionesdatacontext, realizo las operaciones necesarias y por ultimo utilizo el log generado por ejemplo para incluirlo en una tabla de auditoria. Ej:

      'instanciar el objeto bd utilizando la clase bdRemisionesDataContext
Using bd As New bdRemisionesDataContext()
Dim fecha As Date = CDate(sender.text)

'Utilizar linq para obtener un objeto con los datos de mi base de datos
Dim r = From x In bd.Web_Remisiones
Select x
Where x.IdRemision = idremision

Dim remision As New Web_Remisione()
remision = r.First
'Modificar el valor de una propiedad de mi objeto remisiones

remision.FechaEntrega = fecha

'Al utilizar submitchanges el datacontext genera la sentencia update y actuliza el registro en la base de datos
bd.SubmitChanges()

'Utilizo mi claye de ayuda Helper para registrar el log de la transaccion
'Notese que con el obejeto bd puedo utilizar el método creado GetLogStr para
'obtener la cadena con el log de la transacción.

Using h As New Helper
h.InsertarAuditoria(bd.GetLogStr)
End Using

End Using



La cadena retornada por el método en este caso sería algo asi:

SELECT TOP (1) [t0].[IdRemision], [t0].[Consecutivo], [t0].[FechaRemision], [t0].[HoraRemision], [t0].[Id_Cliente], [t0].[Contacto], [t0].[RemitirA], [t0].[UltimaModificacion], [t0].[IdUsuario], [t0].[FechaCreacion], [t0].[Observaciones], [t0].[FechaEntrega]
FROM [dbo].[Web_Remisiones] AS [t0]
WHERE [t0].[IdRemision] = @p0
-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [2]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 4.0.30319.1

UPDATE [dbo].[Web_Remisiones]
SET [FechaEntrega] = @p10
WHERE ([IdRemision] = @p0) AND ([Consecutivo] = @p1) AND ([FechaRemision] = @p2) AND ([HoraRemision] = @p3) AND ([Id_Cliente] = @p4) AND ([Contacto] = @p5) AND ([RemitirA] = @p6) AND ([UltimaModificacion] = @p7) AND ([IdUsuario] = @p8) AND ([FechaCreacion] = @p9) AND ([Observaciones] IS NULL) AND ([FechaEntrega] IS NULL)
-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [2]
-- @p1: Input Int (Size = -1; Prec = 0; Scale = 0) [2]
-- @p2: Input SmallDateTime (Size = -1; Prec = 0; Scale = 0) [20/12/2010 12:00:00 a.m.]
-- @p3: Input VarChar (Size = 8000; Prec = 0; Scale = 0) [ ]
-- @p4: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [M27]
-- @p5: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [ANGELA RODRIGUEZ]
-- @p6: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [ANGELA RODRIGUEZ CRA 5 CON CLL 25]
-- @p7: Input SmallDateTime (Size = -1; Prec = 0; Scale = 0) [20/12/2010 12:00:00 a.m.]
-- @p8: Input Int (Size = -1; Prec = 0; Scale = 0) [1]
-- @p9: Input SmallDateTime (Size = -1; Prec = 0; Scale = 0) [20/12/2010 09:56:00 p.m.]
-- @p10: Input SmallDateTime (Size = -1; Prec = 0; Scale = 0) [31/12/2010 12:00:00 a.m.]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 4.0.30319.1


Espero les sirva de algo este post y si tienen comentarios y  sugerencias, bienvenidos sean.
Róbinson Moscoso
Bogotá - Colombia