Thursday, 19 February 2009

How enterprise library caches the SP Signatures

I like to share few facts about how enterprise library data access block works on caching the SP signatures.

1. Every class of type ‘Database’ is related to another class called ‘ParameterCache’(relationship is Composition), and this class is mainly responsible for caching the SP signature. ‘SQLDatabase’ is derived from ‘Database’. We don’t need any configuration stuff to enable this, it automatically does.

2. ‘ParameterCache’ internally uses synchronized HashTable for storing the SP Singature’s with ‘ConnectionString:SP Name’ as keys.

3. ‘Database’ class instantiates this ‘ParameterCache’ as static member and this means it scope is limited to AppDomain.

public abstract class Database : IInstrumentationEventProvider
{
static readonly ParameterCache parameterCache = new ParameterCache();


No matter how many SQLDatabase objects we create, only one ParameterCache will exist.

4. Before we execute any SPs, we need to call a function called ‘GetStoredProcCommand’, this function will retrieve the SP Singatures if it is available in Cache else from DB and stores it in Cache.

public virtual DbCommand GetStoredProcCommand(string storedProcedureName,
params object[] parameterValues)
{
parameterCache.SetParameters(command, this);

And this is how I figured it

1. I ran SQL Profiler, and the code that retrieves SP Signature (in this case DataAccessHelper.AssignParameters(), this function internally calls GetStoredProcCommand), I am able to see an entry for ‘[sys].[sp_procedure_params_managed]’. But when I hit it next I am not able to, and it means Cache.

2. To make sure Cache is getting populated, I checked the hash table count before and after execution. It was 0 and 1 respectively.

Enterprise Library Vs Log4Net

I tried to evaluate Log4Net 1.2.10 and Enterprise library Logging Application block 4.0 from development perspective with following things in mind

1. I should be able to log an application state in a simpler and consistent way.
2. Logging shouldn’t be an overhead for me.
3. I should be able to log anything anywhere.
4. Logging shouldn’t be an overhead for application.

And what I didn’t consider is

1. Extensible i.e., writing custom loggers or extending the available loggers. Because the main reason for using these application blocks is to reduce the development/testing time. If I am going to extend, well then I write my own logging application block.
2. Support for output mediums other than DB, File and Event Log.

We take EntLib first,
I started reading the Microsoft documentation and to be frank in few minutes time I got exhausted with details I need to know about logging.

I created an application that consumes logging block and luckily they provided us with a graphical configuration tool that took some pain away, but indeed it tells us that configuration is cumbersome in enterprise library blocks.
Ok, then code for logging look something like below

LogEntry logEntry = new LogEntry();
logEntry.EventId = 100;
logEntry.Priority = 2;
logEntry.Message = "Informational message";
logEntry.Categories.Add("Trace");
logEntry.Categories.Add("UI Events"); //This is for filtering the messages.
Logger.Write(logEntry);


It is not mandatory to pass EventID or Priority, but it might be useful when we want to give some context to the log entries.
And enterprise libraries integrate very well.

Then we come to Log4Net,

Logging is really simple in terms of understanding the concept and implementation, still configuration is somewhat messy but it is better than Logging application block because I am able to understand them better.

And Code is really simple
Logger.Info("message"); //overloads are available to pass object with exception details etc.

Apart from these, whatever we can do in Logging application block, same can be done in Log4Net. But there is something more as well
Log4net comes with an appender called ‘
BufferingForwardingAppender’ it means we can buffer the log entries for a configured count before they are flushed out.

Microsoft have similar stuff (I think they copied this), but we can only turn on/off the ‘AutoFlush’, but manually we have to flush it (code).

Object management is well handled by Log4Net framework; it means we don’t need to pass the logger object across components.

Several websites points out that Log4net is faster than Logging application block, though those results depend on various factors but ultimately we want our application to run as fast as possible.

Finally, Logging application block 4.0 comes with WCF support etc, but if it can’t do what it is intended to do in a simple and effective way, who cares about these extras.

The above are my observations and I didn’t conclude anything by referring any websites. Even though I support Microsoft strongly, I am against them in this particular case.