|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionVisual Studio automatically generates the subclasses of BackgroundIn my project, I have a well established logging framework that uses Log4Net. Now that I moved to LINQ to SQL, I needed to get the raw SQL that is generated from the LINQ C# codes for both instrumentation and performance purposes. From MSDN, I came to know that I need to pass an instance of type I hope that the readers of this article with a similar requirement may find it useful in their projects as well. Using the CodeI will be on code-description-code-description mode in this article and discuss the key parts of the sample code. Please click the download link at the top for the full source code of the sample application that I wrote for this article. The Class DiagramThe source code contains a few interfaces and classes. The class diagram of the sample application is as follows:
The ILogger InterfaceI have created an interface with the methods that I use for logging. This interface allows me to extract the dependency on Log4Net or whatever logging framework I am using. This simple interface is presented in the following code segment: namespace LINQ2Log4Net
{
// An interface for loggers.
public interface ILogger
{
// This method creates a logger for specified class
void CreateLogger(Type loggerType);
// Indexer for setting properties for logging
string this[string propertyName]
{
set;
}
//These methods log in various logging levels
void Debug(string message);
void Fatal(string message);
void Info(string message);
void Error(string message);
void Warn(string message);
}
}
The Log4NetLogger : ILogger Class
namespace LINQ2Log4Net
{
/// <summary>
/// This is an implementation of ILogger interface which uses log4net for logging.
/// </summary>
public class Log4NetLogger : ILogger
{
private ILog log;
public void CreateLogger(Type loggerType)
{
log = LogManager.GetLogger(loggerType);
}
// An implementation of interface indexer for setting logging properties.
public string this[string propertyName]
{
set { ThreadContext.Properties[propertyName] = value; }
}
// An implementation of interface method for logging Debug messages
public void Debug(string message)
{
if (log.IsDebugEnabled)
log.Debug(message);
}
// An implementation of interface method for logging Fatal messages
public void Fatal(string message)
{
if (log.IsFatalEnabled)
log.Fatal(message);
}
// An implementation of interface method for logging Info messages
public void Info(string message)
{
if (log.IsInfoEnabled)
log.Info(message);
}
// An implementation of interface method for logging Error messages
public void Error(string message)
{
if (log.IsErrorEnabled)
log.Error(message);
}
// An implementation of interface method for logging Warning messages
public void Warn(string message)
{
if (log.IsWarnEnabled)
log.Warn(message);
}
}
}
The LINQLogger : System.IO.TextWriter ClassAs I have already mentioned in the introduction, the namespace LINQ2Log4Net
{
public class LINQLogger : TextWriter
{
//The ILogger Instance
private ILogger _logger;
public ILogger Logger
{
get { return _logger; }
set { _logger = value; }
}
//The Log level enum
private LogLevelType _logLevelType;
public LogLevelType LogLevel
{
get { return _logLevelType; }
set { _logLevelType = value; }
}
private Encoding _encoding;
public override Encoding Encoding
{
get
{
if (_encoding == null)
{
_encoding = new UnicodeEncoding(false, false);
}
return _encoding;
}
}
public LINQLogger()
{
}
public LINQLogger(ILogger logger, LogLevelType logLevel)
{
_logger = logger;
_logLevelType = logLevel;
}
public override void Write(string value)
{
switch (_logLevelType)
{
case LogLevelType.Fatal: _logger.Fatal(value); break;
case LogLevelType.Error: _logger.Error(value); break;
case LogLevelType.Warn: _logger.Warn(value); break;
case LogLevelType.Info: _logger.Info(value); break;
case LogLevelType.Debug: _logger.Debug(value); break;
}
}
public override void Write(char[] buffer, int index, int count)
{
Write(new string(buffer, index, count));
}
}
public enum LogLevelType
{
Fatal,
Error,
Warn,
Info,
Debug
}
}
The SampleDBDataContext and the Visitor ClassesThese two classes are auto generated by Visual Studio 2008 and so I am skipping the source code. However, from the class diagram, you can see the properties of the The Example UseIn the following code fragment, you will see an example use scenario of the classes that I have discussed up to now. The key flow is as follows:
//Initialize the Log4Net from the XML
log4net.Config.XmlConfigurator.Configure();
//Create the logger for this class
ILogger logger = new Log4NetLogger();
logger.CreateLogger(typeof(LINQ2Log4Net.Program));
//Create an instance of the LINQLogger
LINQLogger linqLogger = new LINQLogger(logger, LogLevelType.Debug);
//Set the linqLogger to the log of the DataContext
SampleDBDataContext context = new SampleDBDataContext();
context.Log = linqLogger;
//Run some queries in the context
Visitor visitor = new Visitor { Name = "S M Sohan", Country = "Bangladesh" };
context.Visitors.InsertOnSubmit(visitor);
context.SubmitChanges();
int count = (from v in context.Visitors select v).Count();
Console.WriteLine("Total # of visitors = {0}", count);
DisclaimerThe whole intention behind this article is to show you the way to achieve Log4Net logging with LINQ to SQL classes. So, I have intentionally avoided other aspects like exception handling codes to focus on the target spot only. History
|
||||||||||||||||||||||