CodeTrigger  

Code Generation For C#, WPF, WCF, SQL SERVER/ORACLE/MYSQL and Visual Studio 2013-2019

Tutorial - Logging and Exception Handling support (Microsoft Enterprise Library)
CodeTrigger provides advanced support for logging and exception handling. This sample shows how to use it with Microsoft Enterprise Library logger. It is also compatible with other commonly used loggers (such as log4net etc)
This guide has been updated for version 5.1.0.0 (released June 10th 2017)

Microsoft Northwind Sample db

STEP 1 - Ensure you have a relevant test database

The CodeTrigger sample applications are designed to work with your existing database schema to ensure that the samples are as relevant as possible. Ensure that you have a TEST SQL Server/Oracle/MYSQL database handy. CodeTrigger and its associated supplier companies do not accept any liability for data loss whilst using the CodeTrigger product. It is important that you use a test database until you are familiar with the functionality of the generated code. This code sample assumes MSQL DB Server/NORTHWIND test database, but should work with your MYSQL/ORACLE db server and your test database of choice.

Step 2 - Create and build a basic Console App using CodeTrigger

Create a build a simple app using one of the CodeTrigger Wizards, perhaps following one of the basic tutorials.

Step 3 - Modify the CodeTrigger project

Choose the following settings in the Advanced options tab:

Enable logging support: Ticked
Enable exception handling support: Ticked

If you are using Northwind sample test database, select 'BOEmployees' in the Business Objects tab, (If you are not using the Northwind sample test database, select suitable objects from those listed in your Business Objects tab) and click Generate Code to generate the files.

Step 4 - Modify the generated xxx_BaseData.cs class

Modify the generated HandleException method stub in the generated basedata class
                    
#region exception handling support
static partial void HandleException(object o, Exception ex);
static protected void Handle(object o, Exception ex, [CallerMemberName] string memberName = "")
{
    //HandleException(o, ex, memberName);
    throw ex;
}
#endregion
                    
                    
Important: Add the modified xxx_BaseData.cs filename to the 'Escaped Files List' in CodeTrigger advanced options tab, to avoid your changes being overwritten.

Step 5 - Add a reference to the Microsoft Enterprise Library modules

Add project references to the modules (download and install Microsoft Enterprise Library if you havent got it yet):

Microsoft.Practices.EnterpriseLibrary.Common
Microsoft.Practices.EnterpriseLibrary.Logging
System.Configuration

Now add a file called xxx_BaseBusiness_Extension.cs to your project to extend your xxx_BaseBusiness class and add logging and exception handling code according to your preferred policy. (In the code fragment below, if necessary dont forget to change the class name from Northwind_BaseBusiness to match whatever your actual base business class is called, and change the namespace to the appropriate namespace for your project)
Note the additional 'memberName' arguments/parameters to the support methods, these are only necessary if you added the optional 'memberName' parameter in Step 4 above.
                    
/*Northwind_BaseBusiness_Extension.cs - extends generated Northwind_BaseBusiness*/
using System;
using System.IO;
using System.Configuration;
using System.Xml.Serialization;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;
using Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;
namespace LoggingAndExceptionSample
{
    public static class Category
    {
        public const string Error = "Error";
        public const string Info = "Info";
    }
    /******************************************************/
    /******************************************************/
	public partial class Northwind_BaseBusiness 
	{
        #region exception support
        static partial void HandleException(object o, Exception ex, string memberName)
        {
            string typeName = "";
            if (o != null) typeName = o.GetType().FullName;
            /*you can choose to swallow or rethrow all or some exceptions according to policy*/
            throw new Exception("Error occurred in " + typeName + ":" + memberName + ". This error has been logged", ex);
        }
        #endregion

        #region logging support
        static string _logginglevel = "NORMAL";
        static Northwind_BaseBusiness()
        {
             Logger.SetLogWriter(new LogWriterFactory().Create());
            Logger.Write("Northwind_BaseBusiness:Start", Category.Info);
            string configLogLevel = ConfigurationManager.AppSettings["logginglevel"];
            _logginglevel = ((configLogLevel != null) ? configLogLevel.ToUpper() : _logginglevel);
        }

        public static string SerializeObject(object toSerialize)
        {
            XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());
            StringWriter textWriter = new StringWriter();
            xmlSerializer.Serialize(textWriter, toSerialize);
            return textWriter.ToString();
        }

        static partial void LogDoing(object o, string memberName)
        {
            string typeName = "";
            if (o != null) typeName = o.GetType().FullName;
            string message = typeName + ":" + memberName + ":Start";
            if (_logginglevel == "VERBOSE" && (o != null))
                message += SerializeObject(o);
            Logger.Write(message, Category.Info);
        }

        static partial void LogDone(object o, string memberName)
        {
            string typeName = "";
            if (o != null) typeName = o.GetType().FullName;
            string message = typeName + ":" + memberName + ":Done";
            if (_logginglevel == "VERBOSE" && (o != null))
                message += SerializeObject(o);
            Logger.Write(message, Category.Info);
        }

        static partial void LogFailed(object o, Exception ex, string memberName)
        {
            string typeName = "";
            if (o != null) typeName = o.GetType().FullName;
            string message = typeName + ":" + memberName + ":Failed";
            message += " Exception:" + ex.Message;
            if (ex.InnerException != null) message += " InnerException:" + ex.InnerException.Message;
            message += " StackTrace:" + ex.StackTrace;
            if (_logginglevel == "VERBOSE" && (o != null))
                message += SerializeObject(o);
            Logger.Write(message, Category.Error);
        }
        #endregion
	}
}
                    
                    
Build your project to make sure it builds successfully and fix any namespace issues.

Step 6 - Add the relevant config entries to your App.config file for the logger

Add the following config entries to the 'configuration' section of your app.config file for logger initialisation. Insert just below your top level 'configuration' element:
                    
<configSections>
    <section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings,
             Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
             requirePermission="true" />
</configSections>
<loggingConfiguration name="" tracingEnabled="true" defaultCategory="General">
    <listeners>
        <add name="Rolling Flat File Trace Listener"
            type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener,
            Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData,
            Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            fileName="c:\Logs\test.rolling.log" footer="End Log Entry." 
            formatter="Text Formatter" header="Log Entry: "
            traceOutputOptions="DateTime, Timestamp" />
    </listeners>
    <formatters>
        <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, 
            Microsoft.Practices.EnterpriseLibrary.Logging,
            Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            template="Category:{category} Message:{message} Timestamp:{timestamp}" name="Text Formatter" />
    </formatters>
    <categorySources>
        <add switchValue="All" name="Info">
            <listeners>
                <add name="Rolling Flat File Trace Listener" />
            </listeners>
        </add>
        <add switchValue="All" name="Error">
            <listeners>
                <add name="Rolling Flat File Trace Listener" />
            </listeners>
        </add>
    </categorySources>
    <specialSources>
        <allEvents switchValue="All" name="All Events" />
        <notProcessed switchValue="All" name="Unprocessed Category" />
        <errors switchValue="All" name="Logging Errors and Warnings" />
    </specialSources>
</loggingConfiguration>

                    
                    
Add the following key value to your app.config file in the 'appSettings' section.
<add key="logginglevel" value="verbose"/>

Step 7 - Write some code to test our your logging and exception handling Implementation

You are ready to test out your logging and exception handling implementation. Here is some code that (using the Northwind sample database) shows retrievals and updates to an employee record, and a forced exception that gets handled (and rethrown). Set your log viewer to watch the log file as setup in your config file (c:\Logs\test.rolling.log)
                    
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LoggingAndExceptionSample
{
    class Program
    {
        static void Main(string[] args)
        {
            string originalFirstName = "";
            int invalidReportingLine = -1;
            /*loading this objects data will write to the log*/
            Console.WriteLine("Selecting one object from db");
            BOEmployees boEmployee = new BOEmployees(1);
            originalFirstName = boEmployee.FirstName;
            Console.WriteLine("Employee first name: " + originalFirstName);
            
            /*updating this objects data will write to the log*/
            boEmployee.FirstName = "Test Name";
            boEmployee.Update();
            Console.WriteLine("Employee first name updated to : " + boEmployee.FirstName);
            /*restore the objects data*/
            boEmployee.FirstName = originalFirstName;
            boEmployee.Update();
            Console.WriteLine("Employee first name restored to : " + originalFirstName);
            /*cause an exception, this will be handled, and rethrown as per our exception handling code*/
            Console.WriteLine("Deliberately going to cause an error here so we can log it");
            boEmployee.ReportsTo = invalidReportingLine;
            try{    boEmployee.Update(); }
            catch(Exception ex){    Console.WriteLine(ex.Message); }
            Console.WriteLine("");
            Console.WriteLine("");
            Console.WriteLine("Demo complete. lookup the logs in the log file as listed in app.config.");
            Console.WriteLine("as listed in app.config 'c:\\logs\\test.rolling.log'");
            Console.WriteLine("Test complete. Press any key to exit");
            Console.ReadLine();
        }
    }
}