Wednesday, June 17, 2009

Call Handler using Enterprise Library's Caching Application Block

As most EntLib users know, the CachingCallHandler provided out-of-the-box does not leverage the feature of its Caching Application Block. I've created my own implementation of an ICallHandler which copies basically the same functionality of the CachingCallHandler but have it use entlib's CAB. As always, if you want a copy of it, just mail me at pinkstarfish.305@gmail.com.

Custom DbTraceListener w/ Custom Exception Handler

This blog discusses how to have a database tracelistener which can log other information other than those which are provided by Enterprise Library's FormattedDatabaseTraceListener in conjuction with handling exceptions. Here are the steps:



1. Create a custom Log Entry:

public class CustomLogEntry: LogEntry

{

public string ContextId //this is the extra information i want to log

{

get;

set;

}

}



2. Create a custom exception handler which you can do either by implementing the IExceptionHandler interface or having your custom handler derive from the LoggingExceptionHandler as well.

[ConfigurationElementType(typeof(CustomHandlerData))]

public class MyLoggingExceptionHandler : LoggingExceptionHandler, IExceptionHandler

{

public override void WriteToLog(string logMessage, IDictionary data)

{

CustomLogEntry log = new CustomLogEntry(); // I created a CustomLogEntry

instead of a LogEntry



log.ContextId = Thread.CurrentContext.ContextID;

log.Message = logMessage;

log.Categories.Add(configAttributes["LogCategory"]);

log.Severity = System.Diagnostics.TraceEventType.Error;

foreach (DictionaryEntry dataEntry in exceptionData)

{

if (dataEntry.Key is string)

{

log.ExtendedProperties.Add(dataEntry.Key as string,

dataEntry.Value);

}

}

Logger.Write(log);

}

}



3. Create the custom database tracelistener which would log the LogEntry informations as well as those extra information available in a CustomLogEntry object.



4. Override the TraceData method of the CustomTraceListener. Check if the data parameter is an instance of a CustomLogEntry. If it is, call the Write(object o) method.



5. Override the Write(object o) method. This will be the place where you would create your DbCommand object and its parameters based on a CustomLogEntry object.



[ConfigurationElementType(typeof(CustomTraceListenerData))]

public class MyDatabaseTraceListener : CustomTraceListener

{

public override void TraceData(System.Diagnostics.TraceEventCache eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, object data)

{

if (data is CustomLogEntry)

{

Write(data);

}

else

{

base.TraceData(eventCache, source, eventType, id, data);

}

}



public override void Write(object o)

{

CustomLogEntry myLog = o as CustomLogEntry;

Database db = DatabaseFactory.CreateDatabase();

DbCommand dbCommand = db.GetStoredProcCommand(

this.Attributes["WriteLogSp"]);

db.AddInParameter(dbCommand, "contextId", System.Data.DbType.Int32, (int)

myLog .Severity);

//add other parameters

db.ExecuteNonQuery(dbCommand);

}

}





That's it. If you want the full working example, you can mail me at pinkstarfish.305@gmail.com. I did hardcode some of the values but remember you can opt to include them in the Attributes collection property of the custom exceptionhandler and customtracelistener.