Using Dispose for auditing?

J

Jonas

Hi!

I'm developing the middletiers of an ASP.NET application in VB.NET. I've got
a business logic layer in which I would like to perform auditing to a
database. Instead of making an auditing call in every method of my classes,
would it be a workable way to implement IDisposable in the base class to all
the BLL-classes and then in the Dispose method to do the audit call? Do I
then have to make sure that all uses of the BLL-classes end with a call to
the Dispose-method or can I count on the garbage collector for this?

TIA

Jonas
 
M

Marina

First of all, I am not clear on how figuring out when classes get garbage
collected are going to help audit changes to a database? Or are you auditing
something else? Can you please be clear on this?

Also, just because an object had Dispose called on it does *not* mean it is
garbage collected. Objects implement IDisposable, so the garbage collector
can call Dispose on it before collecting it - to make sure all resources
were closed prior to collection. But calling Dispose does nothing to make
the GC run. Neither does setting the variable to Nothing, or any other
thing.

The GC will run when it is deemed necessary by the runtime.
 
J

Jonas

Hi again!

I guess I wasn't as clear as I thought :)

I have a bunch of classes in my business layer that handle different kinds
of business entities (vehicles, users, patients ...) Each class has a number
of methods (List, Create, Read, Update, Delete) that I would like to audit.
For example if user A does a List of vehicles and the decides to Delete a
vehicle, I want this to be show in an audit log which I have in the
database. This is necessary for being able to trace who has done what . Now
my methods look like this (very much simplified of course):

Class Vehicle

Function List(userId as Integer) as DataSet
Dim dc as New VehicleDataAccessLayerComponent

If Permission.Check("VehicleList", userId) Then
dc = dc.List()
End If

Audit.Create("VehicleList", userId, ....)
End Function

End Class

Instead of having a call to Audit.Create in every method, I thought it might
be possible to do this in the Dispose method of the Vehicle class (or a
preferably a base class perhaps):

Class Vehicle2

Dim _methodName as String
Dim _userId as Integer

Sub New(userId as Integer)
_userId = userId
End Sub

Function List(userId as int) as DataSet
Dim dc as New VehicleDataAccessLayerComponent
_methodName = "VehicleList"

If Permission.Check(_methodName, userId) Then
dc = dc.List()
End If

End Function

Sub Dispose()
Audit.Create(_methodName, _userId, ....)
End Sub

End Class

The ideas was to get the auditing done in one place for all methods, but
perhaps this give me more problems than it solves ....

TIA

Jonas
 
M

Marina

I see. You are not looking for an audit at the database level of what
columns changed from what values to what values. You want a record of
everything that happened at a higher level.

Well, if you read my description of how garbage collection works, you will
see that your method will not solve the problem you are trying to achieve.

Additionally, using that model only the last action on the object would be
audited. Not all of them.
 
C

Chris, Master of All Things Insignificant

Just a thought but why not do all of your DB changes in Stored Procedures.
This way you can do the audit log on the server side. You can then also
modify the procedures w/o recompiling code if let's say you want more audits
done.

Chris
 
J

Jonas

I'll guess I have to call Dispose on the business classes explicitly for
this to work then.

To get all methods audited, I was thinking of having an array which every
method inserts an entry to audit in, which will be run through by the
Dispose method and thereby auditing all calls.

But perhaps it is better to follow the KISS principle, this solution feels a
bit complicated ..

Thanks for you answers

Jonass
 
J

Jonas

Hi

I actually did the auditing in the database in an earlier version. The most
obivious advantage is performance, but one disadvantage is that I have to
send auditing information like user, ipaddress and so on to every stored
procedure called. I also want to get the audit done on a higher level,
enabling me to replace my homegrown solution with another more easily. It
would also be nice to easily be able to change the destination of the audit
to another storage (filesystem, enterprise audit system ...). It feels
easier to do these things if I'm in .NET instead of SQL Server.

Brgds

Jonas
 
C

Cor Ligthert

Ok, what are the reasons for not doing overloads?One of the exceptional reasons when the dispose is needed is in applications
when they are overloaded, so you make that even more worse.

For the rest should normally (when you have not added unmanaged resources)
the base implementation be enough to do its work.

Now you create a reason that it should be everywhere in a program.
For the same can you than in my opinion create your own not confusing
method.

To understand this more search this dotNet newsgroups for the
connection.dispose, which is needed in version 1.x to handle the
connectionpooling (this is changed in version 2.0)

Cor
 
S

Stefan

Just a thought on the topic,

For the higher level solution I would definitely use a base class or an
interface. If you are already building a big solution you should already
have a basic bass class for your middle tier already.

If you use an Interface you could have your data access methods
(assuming you have a separate DLL comprised of actual ADO.NET code) use
reflection to check if the interface is implemented on that particular
object and if so make the audit call.

I realize I have deviated a bit off topic but this might give him an
idea for audit implementation.

Happy Coding,

Stefan
C# GURU
www.DotNETovation.com

"You always have to look beyond the horizon and can never be complacent
-- God forbid we become complacent."

Jozef Straus
 
J

Jay B. Harlow [MVP - Outlook]

Marina,
Objects implement IDisposable, so the garbage collector can call Dispose
on it before collecting it - to make sure all resources were closed prior
to collection.
Unfortunately the garbage collector never calls Dispose or use IDisposable!
It will call Object.Finalize if your class overrides it, however making the
GC call Finalize might cause your object to hang around in memory
significantly longer then it should (possibly adding pressure to the GC).

The common practice is to have Finalize & Dispose both call
Dispose(boolean).
http://msdn.microsoft.com/library/d.../en-us/cpgenref/html/cpconFinalizeDispose.asp

Otherwise I agree with your statements/questions...

Hope this helps
Jay
 
C

Cor Ligthert

Jay,

This is a page about "implementing" dispose, I see this in my opinion to
seldom when people are using all kind of unmanaged resources, it cannot be
said enough.

Maybe I understand your statement wrong, however Marina and I are figthing
together to the messages that dispose should always be *called* when it is
implemented in the base class.

While it should be implemented in every class that holds unmanaged resources
so do that when it goes out of scope those are cleaned up (I hope I write
this in a way you understand what I want to tell).

Cor
 
J

Jay B. Harlow [MVP - Outlook]

Cor,
This is a page about "implementing" dispose, I see this in my opinion to
seldom when people are using all kind of unmanaged resources, it cannot be
said enough.
Yes its a page on implementing Dispose, as I used it to show how Dispose &
Finalize both call Dispose(Boolean)...

There is a link to the section of MSDN on the how & why of the GC...
Maybe I understand your statement wrong, however Marina and I are figthing
together to the messages that dispose should always be *called* when it is
implemented in the base class.
I was only commenting on the fact that the GC does not call Dispose. It is
up to you if you want to call it explicitly or not. I normally try to
explicitly call it.
While it should be implemented in every class that holds unmanaged
resources so do that when it goes out of scope those are cleaned up (I
hope I write this in a way you understand what I want to tell).
As long as you explicitly call it! I normally call it in a Finally block of
a Try/Finally. VS.NET 2005 adds the Using statement to simplify calling
Dispose.

Hope this helps
Jay
 
J

Jay B. Harlow [MVP - Outlook]

Doh!
I was only commenting on the fact that the GC does not call Dispose. It is
up to you if you want to call it explicitly or not. I normally try to
explicitly call it.
Maybe I should state that the GC does not directly call Dispose.

Obviously if Dispose & Finalize both call Dispose(Boolean) then the GC will
eventually indirectly call Dispose. However! the object needs to hang around
in memory until the GC gets to calling Finalize, this hanging around may
cause extra pressure on the GC...

Ergo I normally try to call Dispose when I am done with the object...

Hope this helps
Jay
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top