Monday, July 1, 2013

IBATIS.NET Developer Guide

5. IBATIS.NET Developer Guide

5.1. Installing the Data Mapper for .NET

5.1.1. Setup the Distribution

            You can download the latest version of IBATIS.NET from the below official site: http://code.google.com/p/mybatisnet/downloads/list

            I'm going to download the IBatis.DataMapper.1.6.2.bin.zip

            List of file found under the distribution's source folder of IBatis.DataMapper.1.6.2.bin.zip

Folder name
Description
Castle.DynamicProxy
Creating Proxy
IBatisNet.Common
Assembly of classes shared by DataAccess and DataMapper
IBatisNet.Common.Logging.Log4Net
Log4Net factory adapter classes
iBatisNet.DataMapper
The DataMapper framework
Log4Net
Log4Net factory adapter Base classes
providers.config
The database provider definition file (XML Configuration file)
sample.SqlMap.config
The Data Mapper configuration file (XML Configuration file)
SqlMap.xml
The Data Map definition file (XML Schema File)

           
5.1.2. Add Assembly References

            Add references to the following files

1.   Castle.DynamicProxy.dll
2.   iBatisNet.DataMapper.dll
3.   iBatisNet.Common.dll
           

            


                        IBatis.NET references

5.1.3. Add XML File Items

            Add following xml files to your application

1.   providers.config
2.   sample.SqlMap.config 
3.   SqlMap.xml


            


                        IBatis.NET XML files

5.2. Provider Configuration File

            I want to connect my application to SQL Server 2005, so removed all the other provider section and maintain "sqlServer2005" provider section alone.
            Ensure that the enabled attribute is set to true; this is set to false by default in the sample installation files.


            


                                                            Provider Configuration

5.3. Data Mapper Configuration File

            Create a copy of sample.SqlMap.config file and rename it with sqlMap.config



5.3.1. The Element

            Name attribute from the "provider.config"  file to be defined here based on any one of the database  (SQL Server, Oracle, Access, and MySql).

            Example:
           
                       

5.3.2. The element

            The element specifies ODBC datasource or connection string for any one database (SQL Server, Oracle, Access, and MySql).

5.3.3. The Element

            elements for loading a set of Data Map definition. Note that the elements are nested in a element.

            Example:

                       
                                   
                                   
                       


5.4. Create a map

            Add another XML file to the root of your project called UsersMap.xml.



5.5. Building a SqlMapper Instance

            The framework provides service methods that you can call which read the configuration file (and any of its definition files) and builds a SqlMapper object. The SqlMapper object provides access to the rest of the framework. The SqlMapper is designed to be multi-threaded and long-lived, and so makes for a good singleton.

            Code:

                        using IBatisNet.Common.Utilities;
                        using IBatisNet.DataMapper;
                        using IBatisNet.DataMapper.Configuration;

                        namespace DataMapper
                        {
                                    public class Mapper
                                    {
                                    private static volatile ISqlMapper _mapper = null;

                                    protected static void Configure(object obj)
                                    {
                                                _mapper = null;
                                    }

                                    protected static void InitMapper()
                                    {
                                                ConfigureHandler handler = new ConfigureHandler(Configure);
                                                DomSqlMapBuilder builder = new DomSqlMapBuilder();
                                                _mapper = builder.ConfigureAndWatch(handler);
                                    }

                                    public static ISqlMapper Instance()
                                    {
                                                if (_mapper == null)
                                                {
                                                            lock (typeof(SqlMapper))
                                                            {
                                                            if (_mapper == null) // double-check
                                                            {
                                                                        InitMapper();
                                                            }
                                                            }
                                                }
                                                return _mapper;
                                    }

                                    public static ISqlMapper Get()
                                    {
                                                return Instance();
                                    }
                                    }
                        }

5.6. Code to execute IBATIS.Net

            Code:

                        The DataLayer looks like below

                        using System;
                        using System.Collections.Generic;
                        using System.Web;
                        using System.Xml;

                        using IBatisNet.Common;
                        using IBatisNet.Common.Utilities;
                        using IBatisNet.DataMapper;
                        using IBatisNet.DataMapper.Configuration;
                        using DataMapper;

                        namespace IBATIS
                        {
                                    public class DataLayer
                                    {
                                                public static IList<PVCSummary> PVCReport(string XMLPARAM, int PAGENUMBER, string PAGING)
                                    {
                                                parameters pm = new parameters();
                                                pm.XMLPARAM = XMLPARAM;
                                                pm.PAGENUMBER = PAGENUMBER;
                                                pm.PAGING = PAGING;

                                                IList<PLANNEDVSCOMPLETED> objPvCReport = DataMapper.Mapper.Instance()
                                                                                                                        .QueryForList<PLANNEDVSCOMPLETED>("PVCReport", pm);
                                                return objPvCReport;
                                    }
                                    }

                                    public class parameters
                                    {
                                                public virtual string XMLPARAM { get; set; }
                                                public virtual int PAGENUMBER { get; set; }
                                                public virtual string PAGING { get; set; }
                                    }
                        }

                        The codebehind of aspx page as shown below

                        protected void Page_Load(object sender, EventArgs e)
                        {
                                    string Param = "";          //xml parameter

                                    IList<PLANNEDVSCOMPLETED> objReport = DataLayer.PVCReport(Param, 1, "Y");
                                    lstvw.DataSource = objReport;              //assign result object directly to listview datasource
                                    lstvw.DataBind()

                        }

Generate class and properties at runtime

To generate a class and properties at run-time.

using System;
using System.Data;
using System.Reflection;
using System.Collections.Generic;

namespace ReportEngine
{
    class Program
    {
        static void Main(string[] args)
        {

            DataTable table = InputGeneration.GetTable();

            //InputGeneration.DisplayTable(table);


            #region "Method2 - Generate class and properties alone at runtime"

            Console.WriteLine("\n---Method2 - Generate class and properties alone at runtime--------------\n");

            IEnumerableDynamicProperty> properties = Method2.GenerateProperties(table);

            Type type = Method2.GenerateClass(properties);

            //The below combination will return all non-public instance properties on the type.
            var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

            PropertyInfo[] props = type.GetProperties(flags);
            for (int i = 0; i < props.Length; i++)
            {
                Console.Write("\t{0}\t", props[i].Name);
            }
            Console.WriteLine("\t");

            Method2 m2 = new Method2();
            m2.AssignClassValues(type, table);


            #endregion

            Console.WriteLine("\n---------------------------------------------------------\n");

            Console.ReadLine();
        }
    }
}

InputGeneration:

using System;
using System.Data;

namespace ReportEngine
{
    public static class InputGeneration
    {
        public static DataTable GetTable()
        {
            //
            // Here we create a DataTable with four columns.
            //
            DataTable table = new DataTable();
            table.Columns.Add("Dosage", typeof(int));
            table.Columns.Add("Drug", typeof(string));
            table.Columns.Add("Patient", typeof(string));
            table.Columns.Add("Date", typeof(DateTime));

            //
            // Here we add five DataRows.
            //
            table.Rows.Add(25, "Indocin", "David", DateTime.Now);
            table.Rows.Add(50, "Enebrel", "Sam", DateTime.Now);
            table.Rows.Add(10, "Hydralazine", "Christoff", DateTime.Now);
            table.Rows.Add(21, "Combivent", "Janet", DateTime.Now);
            table.Rows.Add(100, "Dilantin", "Melanie", DateTime.Now);
            return table;
        }

        public static void DisplayTable(DataTable dt)
        {
            if (dt.Rows.Count > 0)
            {
                foreach (DataColumn column in dt.Columns)
                {
                    Console.Write("\t{0}\t", column.ColumnName);
                }
                Console.WriteLine("\t");
                foreach (DataRow row in dt.Rows)
                {
                    foreach (DataColumn column in dt.Columns)
                        Console.Write("\t{0}\t", row[column]);

                    Console.WriteLine("\t");
                }
            }
            else
                Console.WriteLine("No Current Rows Found");
        }
    }
}

Method2:

using System;
using System.Data;
using System.Collections.Generic;
using ReportEngine.ClassAtRuntime;
using System.Reflection;

namespace ReportEngine
{
    public class Method2
    {
        public static IEnumerable<DynamicProperty> GenerateProperties(DataTable table)
        {
            List<DynamicProperty> Properties = new List<DynamicProperty>();
            foreach (DataColumn column in table.Columns)
            {
                Properties.Add(new DynamicProperty(column.ColumnName.ToUpper(), column.DataType));
            }

            return Properties;
        }

        public static Type GenerateClass(IEnumerable<DynamicProperty> properties)
        {
            Type type = Dynamic.CreateClass(properties);
            return type;
        }

        public void AssignClassValues(Type type, DataTable table)
        {
            List<object> lstobj = new List<object>();

            foreach (DataRow dr in table.Rows)
            {
                var obj = Activator.CreateInstance(type);
                PropertyInfo[] props = obj.GetType().GetProperties();
                for (int i = 0; i < props.Length; i++)
                {
                    if (props[i].CanWrite)
                    {
                        try
                        {
                            if (dr[props[i].Name] != null && !dr.IsNull(props[i].Name))
                            {
                                props[i].SetValue(obj, dr[props[i].Name], null);
                            }
                            else
                            {
                                props[i].SetValue(props[i].Name, null, null);
                            }
                        }
                        catch // DB COLUMN does not exist for this property.
                        {
                            props[i].SetValue(props[i].Name, null, null);
                        }
                    }
                }
                lstobj.Add(obj);
            }
        }

        public void ReadClassValues(List<object> lstobj)
        {
            foreach (object obj in lstobj)
            {
               
            }
        }

        public void getModelFromObject(Type type, DataTable table)
        {
            List el = new List();
            foreach (DataRow dr in table.Rows)
            {
                T item = (T)Activator.CreateInstance(type);
                getObject(dr, ref item, table);
                T tsts = item;

                ((List)el).Add(item);

            }
        }

        public void getObject(DataRow dr, ref T obj, DataTable dt)
        {

            foreach (DataColumn dc in dt.Columns)
            {
                if (obj.GetType().GetProperty(dc.ColumnName) != null)
                {
                    obj.GetType().GetProperty(dc.ColumnName).SetValue(obj, dr[dc.ColumnName], null);
                }
            }
        }

    }
}



DynamicClasswithProperties:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;

namespace ReportEngine.ClassAtRuntime
{

    class DynamicClasswithProperties
    {
    }

    public abstract class DynamicClass
    {
        public override string ToString()
        {
            PropertyInfo[] props = this.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
            StringBuilder sb = new StringBuilder();
            sb.Append("{");
            for (int i = 0; i < props.Length; i++)
            {
                if (i > 0) sb.Append(", ");
                sb.Append(props[i].Name);
                sb.Append("=");
                sb.Append(props[i].GetValue(this, null));
            }
            sb.Append("}");
            return sb.ToString();
        }
    }

    public class DynamicProperty
    {
        string name;
        Type type;

        public DynamicProperty(string name, Type type)
        {
            if (name == null) throw new ArgumentNullException("name");
            if (type == null) throw new ArgumentNullException("type");
            this.name = name;
            this.type = type;
        }

        public string Name
        {
            get { return name; }
        }

        public Type Type
        {
            get { return type; }
        }
    }

    public static class Dynamic
    {
        public static Type CreateClass(IEnumerable<DynamicProperty> properties)
        {
            return ClassFactory.Instance.GetDynamicClass(properties);
        }
    }
    internal class Signature : IEquatable<Signature>
    {
        public DynamicProperty[] properties;
        public int hashCode;

        public Signature(IEnumerable<DynamicProperty> properties)
        {
            this.properties = properties.ToArray();
            hashCode = 0;
            foreach (DynamicProperty p in properties)
            {
                hashCode ^= p.Name.GetHashCode() ^ p.Type.GetHashCode();
            }
        }

        public override int GetHashCode()
        {
            return hashCode;
        }

        public override bool Equals(object obj)
        {
            return obj is Signature ? Equals((Signature)obj) : false;
        }

        public bool Equals(Signature other)
        {
            if (properties.Length != other.properties.Length) return false;
            for (int i = 0; i < properties.Length; i++)
            {
                if (properties[i].Name != other.properties[i].Name ||
                    properties[i].Type != other.properties[i].Type) return false;
            }
            return true;
        }
    }

    internal class ClassFactory
    {
        public static readonly ClassFactory Instance = new ClassFactory();

        static ClassFactory() { }  // Trigger lazy initialization of static fields

        ModuleBuilder module;
        Dictionary<Signature, Type> classes;
        int classCount;
        ReaderWriterLock rwLock;

        private ClassFactory()
        {
            AssemblyName name = new AssemblyName("DynamicClasses");
            AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
            #if ENABLE_LINQ_PARTIAL_TRUST
            new ReflectionPermission(PermissionState.Unrestricted).Assert();
            #endif
            try
            {
                module = assembly.DefineDynamicModule("Module");
            }
            finally
            {
            #if ENABLE_LINQ_PARTIAL_TRUST
                PermissionSet.RevertAssert();
            #endif
            }
            classes = new Dictionary<Signature, Type>();
            rwLock = new ReaderWriterLock();
        }

        public Type GetDynamicClass(IEnumerable<DynamicProperty> properties)
        {
            rwLock.AcquireReaderLock(Timeout.Infinite);
            try
            {
                Signature signature = new Signature(properties);
                Type type;
                if (!classes.TryGetValue(signature, out type))
                {
                    type = CreateDynamicClass(signature.properties);
                    classes.Add(signature, type);
                }
                return type;
            }
            finally
            {
                rwLock.ReleaseReaderLock();
            }
        }

        Type CreateDynamicClass(DynamicProperty[] properties)
        {
            LockCookie cookie = rwLock.UpgradeToWriterLock(Timeout.Infinite);
            try
            {
                string typeName = "DynamicClass" + (classCount + 1);
                #if ENABLE_LINQ_PARTIAL_TRUST
                new ReflectionPermission(PermissionState.Unrestricted).Assert();
                #endif
                try
                {
                    TypeBuilder tb = this.module.DefineType(typeName, TypeAttributes.Class |
                        TypeAttributes.Public, typeof(DynamicClass));
                    FieldInfo[] fields = GenerateProperties(tb, properties);
                    GenerateEquals(tb, fields);
                    GenerateGetHashCode(tb, fields);
                    Type result = tb.CreateType();
                    classCount++;
                    return result;
                }
                finally
                {
                    #if ENABLE_LINQ_PARTIAL_TRUST
                    PermissionSet.RevertAssert();
                    #endif
                }
            }
            finally
            {
                rwLock.DowngradeFromWriterLock(ref cookie);
            }
        }

        FieldInfo[] GenerateProperties(TypeBuilder tb, DynamicProperty[] properties)
        {
            FieldInfo[] fields = new FieldBuilder[properties.Length];
            for (int i = 0; i < properties.Length; i++)
            {
                DynamicProperty dp = properties[i];
                FieldBuilder fb = tb.DefineField("_" + dp.Name, dp.Type, FieldAttributes.Private);
                PropertyBuilder pb = tb.DefineProperty(dp.Name, PropertyAttributes.HasDefault, dp.Type, null);
                MethodBuilder mbGet = tb.DefineMethod("get_" + dp.Name,
                    MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,
                    dp.Type, Type.EmptyTypes);
                ILGenerator genGet = mbGet.GetILGenerator();
                genGet.Emit(OpCodes.Ldarg_0);
                genGet.Emit(OpCodes.Ldfld, fb);
                genGet.Emit(OpCodes.Ret);
                MethodBuilder mbSet = tb.DefineMethod("set_" + dp.Name,
                    MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,
                    null, new Type[] { dp.Type });
                ILGenerator genSet = mbSet.GetILGenerator();
                genSet.Emit(OpCodes.Ldarg_0);
                genSet.Emit(OpCodes.Ldarg_1);
                genSet.Emit(OpCodes.Stfld, fb);
                genSet.Emit(OpCodes.Ret);
                pb.SetGetMethod(mbGet);
                pb.SetSetMethod(mbSet);
                fields[i] = fb;
            }
            return fields;
        }

        void GenerateEquals(TypeBuilder tb, FieldInfo[] fields)
        {
            MethodBuilder mb = tb.DefineMethod("Equals",
                MethodAttributes.Public | MethodAttributes.ReuseSlot |
                MethodAttributes.Virtual | MethodAttributes.HideBySig,
                typeof(bool), new Type[] { typeof(object) });
            ILGenerator gen = mb.GetILGenerator();
            LocalBuilder other = gen.DeclareLocal(tb);
            Label next = gen.DefineLabel();
            gen.Emit(OpCodes.Ldarg_1);
            gen.Emit(OpCodes.Isinst, tb);
            gen.Emit(OpCodes.Stloc, other);
            gen.Emit(OpCodes.Ldloc, other);
            gen.Emit(OpCodes.Brtrue_S, next);
            gen.Emit(OpCodes.Ldc_I4_0);
            gen.Emit(OpCodes.Ret);
            gen.MarkLabel(next);
            foreach (FieldInfo field in fields)
            {
                Type ft = field.FieldType;
                Type ct = typeof(EqualityComparer<>).MakeGenericType(ft);
                next = gen.DefineLabel();
                gen.EmitCall(OpCodes.Call, ct.GetMethod("get_Default"), null);
                gen.Emit(OpCodes.Ldarg_0);
                gen.Emit(OpCodes.Ldfld, field);
                gen.Emit(OpCodes.Ldloc, other);
                gen.Emit(OpCodes.Ldfld, field);
                gen.EmitCall(OpCodes.Callvirt, ct.GetMethod("Equals", new Type[] { ft, ft }), null);
                gen.Emit(OpCodes.Brtrue_S, next);
                gen.Emit(OpCodes.Ldc_I4_0);
                gen.Emit(OpCodes.Ret);
                gen.MarkLabel(next);
            }
            gen.Emit(OpCodes.Ldc_I4_1);
            gen.Emit(OpCodes.Ret);
        }

        void GenerateGetHashCode(TypeBuilder tb, FieldInfo[] fields)
        {
            MethodBuilder mb = tb.DefineMethod("GetHashCode",
                MethodAttributes.Public | MethodAttributes.ReuseSlot |
                MethodAttributes.Virtual | MethodAttributes.HideBySig,
                typeof(int), Type.EmptyTypes);
            ILGenerator gen = mb.GetILGenerator();
            gen.Emit(OpCodes.Ldc_I4_0);
            foreach (FieldInfo field in fields)
            {
                Type ft = field.FieldType;
                Type ct = typeof(EqualityComparer<>).MakeGenericType(ft);
                gen.EmitCall(OpCodes.Call, ct.GetMethod("get_Default"), null);
                gen.Emit(OpCodes.Ldarg_0);
                gen.Emit(OpCodes.Ldfld, field);
                gen.EmitCall(OpCodes.Callvirt, ct.GetMethod("GetHashCode", new Type[] { ft }), null);
                gen.Emit(OpCodes.Xor);
            }
            gen.Emit(OpCodes.Ret);
        }
    }
}