API for Unit Of Work Pattern Implementation with Linq To SQL

Development API (code)
Table of Contents
Summary

Source code for the implementation of the namespace DesignPatterns.L2SQL.UnitOfWork.


Operations
IUnitOfWorkFactory.cs
How to do it
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.L2SQL.UnitOfWork
{
    public interface IUnitOfWorkFactory:IDisposable
    {
        IUnitOfWork Create();
        void Dispose();
    }
}
IUnitOfWork.cs
How to do it
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.L2SQL.UnitOfWork
{
    public interface IUnitOfWork : IDisposable
    {
        void Commit();
        void Rollback();
    }
}
UnitOfWorkFactory.cs
How to do it
using System;
using System.Collections.Generic;
using System.Linq;

namespace DesignPatterns.L2SQL.UnitOfWork
{
    public class UnitOfWorkFactory<T> : IUnitOfWorkFactory, IDisposable where T : System.Data.Linq.DataContext
    {
        private string _connectionString = string.Empty;
        private System.Data.Linq.Mapping.MappingSource _mappingSource = null;

        public UnitOfWorkFactory()
        {
            ErrorHandling.LogManager.Log(ErrorHandling.LogManager.LogEntryType.INFORMATION, ErrorHandling.LogManager.LogCategoryType.ORM, Guid.Empty,null, "Unit of work factory created.");
        }

        public IUnitOfWork Create()
        {
            ErrorHandling.LogManager.Log(ErrorHandling.LogManager.LogEntryType.INFORMATION, ErrorHandling.LogManager.LogCategoryType.ORM, Guid.Empty, null, "Create new session/datacontext...");

            return new UnitOfWork(Activator.CreateInstance<T>());
        }

        public void Dispose()
        {
            ErrorHandling.LogManager.Log(ErrorHandling.LogManager.LogEntryType.INFORMATION, ErrorHandling.LogManager.LogCategoryType.ORM, Guid.Empty, null, "Unit of work factory disposed.");
        }
    }
}
UnitOfWork.cs
How to do it
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
using System;
using System.IO;

namespace DesignPatterns.L2SQL.UnitOfWork
{
    public class UnitOfWork : IUnitOfWork
    {
        private string TYPE_OF_ORM = "L2SQL";
        private IDbTransaction _transaction;
        public DataContext CurrentContext { get; private set; }

        internal UnitOfWork(DataContext context)
        {
            CurrentContext = context;
            CurrentContext.Log = ErrorHandling.LogManager.LogChannel;

            ErrorHandling.LogManager.Log(ErrorHandling.LogManager.LogEntryType.INFORMATION, ErrorHandling.LogManager.LogCategoryType.ORM, Guid.Empty, null, "Session/data context " + context.GetHashCode().ToString() + " created [connection string: " + context.Connection.ConnectionString + "].");

        }

        public void BeginTransaction()
        {
            if (CurrentContext.Connection.State == ConnectionState.Closed)
            {
                CurrentContext.Connection.Open();
            }

            _transaction = CurrentContext.Connection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted);
            CurrentContext.Transaction = (System.Data.Common.DbTransaction) _transaction;
            ErrorHandling.LogManager.Log(ErrorHandling.LogManager.LogEntryType.INFORMATION, ErrorHandling.LogManager.LogCategoryType.SQL, Guid.Empty, null, "Started new SQL transaction " + _transaction.GetHashCode().ToString() +".");
        }

        public void Commit()
        {
            if (_transaction != null)
            {
                ErrorHandling.LogManager.Log(ErrorHandling.LogManager.LogEntryType.INFORMATION, ErrorHandling.LogManager.LogCategoryType.SQL, Guid.Empty, null, "Commit current inline transaction... ");
                CurrentContext.SubmitChanges();
            }
            else
            {
                ErrorHandling.LogManager.Log(ErrorHandling.LogManager.LogEntryType.INFORMATION, ErrorHandling.LogManager.LogCategoryType.SQL, Guid.Empty, null, "Commit transacion " + _transaction.GetHashCode().ToString() + "...");
                _transaction.Commit();
            }

            ErrorHandling.LogManager.Log(ErrorHandling.LogManager.LogEntryType.INFORMATION, ErrorHandling.LogManager.LogCategoryType.SQL, Guid.Empty, null, "Transacion " + _transaction.GetHashCode().ToString() + " committed [" + this.CurrentContext.GetChangeSet() + "].");
        }

        public void Rollback()
        {
            if (_transaction != null)
            {
                ErrorHandling.LogManager.Log(ErrorHandling.LogManager.LogEntryType.INFORMATION, ErrorHandling.LogManager.LogCategoryType.SQL, Guid.Empty, null, "Rollback transaction " + _transaction.GetHashCode().ToString() + "...");
                _transaction.Rollback();
                ErrorHandling.LogManager.Log(ErrorHandling.LogManager.LogEntryType.INFORMATION, ErrorHandling.LogManager.LogCategoryType.SQL, Guid.Empty, null, "Transaction " + _transaction.GetHashCode().ToString() + " rolledback.");
            }
        }

        public void Dispose()
        {
            if (CurrentContext!=null)
            {
                ErrorHandling.LogManager.Log(ErrorHandling.LogManager.LogEntryType.INFORMATION, ErrorHandling.LogManager.LogCategoryType.ORM, Guid.Empty, null, "Close session / data context " + CurrentContext.GetHashCode().ToString() + "...");
                CurrentContext.Dispose();
                ErrorHandling.LogManager.Log(ErrorHandling.LogManager.LogEntryType.INFORMATION, ErrorHandling.LogManager.LogCategoryType.ORM, Guid.Empty, null, "Session / data context" + CurrentContext.GetHashCode().ToString() + " closed and disposed.");
            }
        }
    }

}
LogManager.cs
How to do it
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;
using System.Reflection;

namespace ErrorHandling
{
    public class LogManager
    {
        public enum LogEntryType
        {
            ERROR =0,
            WARNING = 1,
            INFORMATION = 2,
            AUDIT = 3
        }

        public enum LogCategoryType
        {
            STARTCOMMAND =0,
            RUNNINGCOMMAND = 1,
            ENDCOMMAND = 2,
            ABORTEDCOMMAND = 3,
            OBJECTDUMP = 4,
            ORM =5,
            SQL = 6,
            UNCATEGORIZED = -1
        }

        private static StreamWriter _sw = null;

        public static StreamWriter LogChannel { get { return _sw; } }

        public static void Init(string pFilePath, string pFileName)
        {
            if (!Directory.Exists(pFilePath))
            {
                throw new  Exception("Invalid directory [" + pFilePath + "]: Unable to initialize log file.");
            }
            else
            {
                _sw =new StreamWriter(pFilePath + "\\" + pFileName);
                _sw.AutoFlush = true;
            }
        }

        public static void Close()
        {
            if (_sw != null) {
                _sw.Flush();
                _sw.Close();
            }
        }

        public static void Write(string pText)
        {
            _sw.WriteLine(pText);
        }

        public static void Log(LogEntryType pType, LogCategoryType pCategory, Guid pOperation, string pSubCategory, string pDescription)
        {
            Log(pType, pCategory, pOperation, pSubCategory, pDescription, null);
        }

        public static void Log(Exception pError, LogCategoryType pCategory, Guid pOperation, string pSubCategory, string pDescription )
        {
            lock (typeof(LogManager))
            {
                var _entry = DateTime.Now.ToString("yyyy/MM/dd hh:mm:ss") + " " + "ERROR".PadRight(12,' ') + " " + pCategory.ToString().PadRight(14,' ') + " " + (pSubCategory == null ? "" : pSubCategory + " ") + (pOperation == Guid.Empty ? "" : "[" + pOperation.ToString() + "]") + ": " + pDescription;
                _entry = _entry + System.Environment.NewLine + System.Environment.NewLine +  pError.ToString();
                _sw.WriteLine(_entry);
                _sw.WriteLine();
            }
        }       

        public static void Log(LogEntryType pType, LogCategoryType pCategory, Guid pOperation, string pSubCategory, string pDescription, Object pObject )
        {
            lock (typeof(LogManager))
            {
                var _entry = DateTime.Now.ToString("yyyy/MM/dd hh:mm:ss") + " " + pType.ToString().PadRight(12,' ') + " " + pCategory.ToString().PadRight(14,' ') + " " + (pSubCategory == null ? "" : pSubCategory + " ") + (pOperation == Guid.Empty ? "" : "[" + pOperation.ToString() + "]") + ": " + pDescription;
                _sw.WriteLine(_entry);

                if (pObject != null)
                {
                    _entry = DateTime.Now.ToString("yyyy/MM/dd hh:mm:ss") + " " + "AUDIT".PadRight(12, ' ') + " " + "OBJECTDUMP".PadRight(14, ' ') + " :" + System.Environment.NewLine;
                    _sw.WriteLine(_entry);
                    ObjectDumper.Write(pObject, 0, _sw);
                    _sw.WriteLine();
                }
            }
        }

    }

    public class ObjectDumper
    {

        public static void Write(object element)
        {
            Write(element, 0);
        }

        public static void Write(object element, int depth)
        {
            Write(element, depth, Console.Out);
        }

        public static void Write(object element, int depth, TextWriter log)
        {
            ObjectDumper dumper = new ObjectDumper(depth);
            dumper.writer = log;
            dumper.WriteObject(null, element);
        }

        TextWriter writer;
        int pos;
        int level;
        int depth;

        private ObjectDumper(int depth)
        {
            this.depth = depth;
        }

        private void Write(string s)
        {
            if (s != null)
            {
                writer.Write(s);
                pos += s.Length;
            }
        }

        private void WriteIndent()
        {
            for (int i = 0; i < level; i++) writer.Write("  ");
        }

        private void WriteLine()
        {
            writer.WriteLine();
            pos = 0;
        }

        private void WriteTab()
        {
            Write("  ");
            while (pos % 8 != 0) Write(" ");
        }

        private void WriteObject(string prefix, object element)
        {
            if (element == null || element is ValueType || element is string)
            {
                WriteIndent();
                Write(prefix);
                WriteValue(element);
                WriteLine();
            }
            else
            {
                IEnumerable enumerableElement = element as IEnumerable;
                if (enumerableElement != null)
                {
                    foreach (object item in enumerableElement)
                    {
                        if (item is IEnumerable && !(item is string))
                        {
                            WriteIndent();
                            Write(prefix);
                            Write("...");
                            WriteLine();
                            if (level < depth)
                            {
                                level++;
                                WriteObject(prefix, item);
                                level--;
                            }
                        }
                        else
                        {
                            WriteObject(prefix, item);
                        }
                    }
                }
                else
                {
                    MemberInfo[] members = element.GetType().GetMembers(BindingFlags.Public | BindingFlags.Instance);
                    WriteIndent();
                    Write(prefix);
                    bool propWritten = false;
                    foreach (MemberInfo m in members)
                    {
                        FieldInfo f = m as FieldInfo;
                        PropertyInfo p = m as PropertyInfo;
                        if (f != null || p != null)
                        {
                            if (propWritten)
                            {
                                WriteTab();
                            }
                            else
                            {
                                propWritten = true;
                            }
                            Write(m.Name);
                            Write("=");
                            Type t = f != null ? f.FieldType : p.PropertyType;
                            if (t.IsValueType || t == typeof(string))
                            {
                                WriteValue(f != null ? f.GetValue(element) : p.GetValue(element, null));
                            }
                            else
                            {
                                if (typeof(IEnumerable).IsAssignableFrom(t))
                                {
                                    Write("...");
                                }
                                else
                                {
                                    Write("{ }");
                                }
                            }
                        }
                    }
                    if (propWritten) WriteLine();
                    if (level < depth)
                    {
                        foreach (MemberInfo m in members)
                        {
                            FieldInfo f = m as FieldInfo;
                            PropertyInfo p = m as PropertyInfo;
                            if (f != null || p != null)
                            {
                                Type t = f != null ? f.FieldType : p.PropertyType;
                                if (!(t.IsValueType || t == typeof(string)))
                                {
                                    object value = f != null ? f.GetValue(element) : p.GetValue(element, null);
                                    if (value != null)
                                    {
                                        level++;
                                        WriteObject(m.Name + ": ", value);
                                        level--;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        private void WriteValue(object o)
        {
            if (o == null)
            {
                Write("null");
            }
            else if (o is DateTime)
            {
                Write(((DateTime)o).ToShortDateString());
            }
            else if (o is ValueType || o is string)
            {
                Write(o.ToString());
            }
            else if (o is IEnumerable)
            {
                Write("...");
            }
            else
            {
                Write("{ }");
            }
        }
    }

}