vs 2015 轻量级orm框架(一)付源码及测试用例

一.数据库和技术应用
数据库orcle,可扩展其他数据库
应用技术 C# Reflection,Reflection.Emit, Attribute

二.数据库连接代码,这段代码是抄的csdn某位仁兄,具体记不得了
代码:DataReader扩展

代码下载

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

namespace DAL
{
    /// <summary>
    /// DataReader Extensions
    /// </summary>
    public static class DataReaderExtensions
    {
        #region Static Readonly Fields
        private static readonly MethodInfo DataRecord_ItemGetter_String =
            typeof(IDataRecord).GetMethod("get_Item", new Type[] { typeof(string) });
        private static readonly MethodInfo DataRecord_ItemGetter_Int =
            typeof(IDataRecord).GetMethod("get_Item", new Type[] { typeof(int) });
        private static readonly MethodInfo DataRecord_GetOrdinal =
            typeof(IDataRecord).GetMethod("GetOrdinal");
        private static readonly MethodInfo DataReader_Read =
            typeof(IDataReader).GetMethod("Read");
        private static readonly MethodInfo Convert_IsDBNull =
            typeof(Convert).GetMethod("IsDBNull");
        private static readonly MethodInfo DataRecord_GetDateTime =
            typeof(IDataRecord).GetMethod("GetDateTime");
        private static readonly MethodInfo DataRecord_GetDecimal =
            typeof(IDataRecord).GetMethod("GetDecimal");
        private static readonly MethodInfo DataRecord_GetDouble =
            typeof(IDataRecord).GetMethod("GetDouble");
        private static readonly MethodInfo DataRecord_GetFloat =
           typeof(IDataRecord).GetMethod("GetFloat");
        private static readonly MethodInfo DataRecord_GetInt32 =
            typeof(IDataRecord).GetMethod("GetInt32");
        private static readonly MethodInfo DataRecord_GetInt64 =
            typeof(IDataRecord).GetMethod("GetInt64");
        private static readonly MethodInfo DataRecord_GetString =
            typeof(IDataRecord).GetMethod("GetString");
        private static readonly MethodInfo DataRecord_IsDBNull =
            typeof(IDataRecord).GetMethod("IsDBNull");
        #endregion


        #region Public Static Methods
        /// <summary>
        /// 把结果集流转换成数据实体列表
        /// </summary>
        /// <typeparam name="T">数据实体类型</typeparam>
        /// <param name="reader">结果集流</param>
        /// <returns>数据实体列表</returns>
        public static List<T> Select<T>(this IDataReader reader)
            where T : class, new()
        {
            if (reader == null)
                throw new ArgumentNullException("reader");
            return EntityConverter<T>.Select(reader);
        }

        /// <summary>
        /// 把结果集流转换成数据实体序列(延迟)
        /// </summary>
        /// <typeparam name="T">数据实体类型</typeparam>
        /// <param name="reader">结果集流</param>
        /// <returns>数据实体序列(延迟)</returns>
        public static IEnumerable<T> SelectLazy<T>(this IDataReader reader)
            where T : class, new()
        {
            if (reader == null)
                throw new ArgumentNullException("reader");
            return EntityConverter<T>.SelectDelay(reader);
        }
        #endregion

        #region Class: EntityConverter<T>

        /// <summary>
        /// 实体转换器
        /// </summary>
        /// <typeparam name="T">数据实体类型</typeparam>
        private class EntityConverter<T>
            where T : class, new()
        {

            #region Struct: DbColumnInfo
            private struct DbColumnInfo
            {
                public readonly string PropertyName;
                public readonly string ColumnName;
                public readonly Type Type;
                public readonly MethodInfo SetMethod;
                public readonly bool IsOptional;

                public DbColumnInfo(PropertyInfo prop, DbColumnAttribute attr)
                {
                    PropertyName = prop.Name;
                    ColumnName = attr.ColumnName ?? prop.Name;
                    Type = prop.PropertyType;
                    SetMethod = prop.GetSetMethod(false);
                    IsOptional = attr.IsOptional;
                }
            }
            #endregion

            #region Fields
            private static Converter<IDataReader, T> dataLoader;
            private static Converter<IDataReader, List<T>> batchDataLoader;
            #endregion

            #region Properties
            private static Converter<IDataReader, T> DataLoader
            {
                get
                {
                    if (dataLoader == null)
                        dataLoader = CreateDataLoader(new List<DbColumnInfo>(GetProperties()));
                    return dataLoader;
                }
            }

            private static Converter<IDataReader, List<T>> BatchDataLoader
            {
                get
                {
                    if (batchDataLoader == null)
                        batchDataLoader = CreateBatchDataLoader(new List<DbColumnInfo>(GetProperties()));
                    return batchDataLoader;
                }
            }
            #endregion

            #region Init Methods
            private static IEnumerable<DbColumnInfo> GetProperties()
            {
                DbResultAttribute dbResult = Attribute.GetCustomAttribute(typeof(T), typeof(DbResultAttribute), true) as DbResultAttribute;
                foreach (var prop in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public))
                {
                    if (prop.GetIndexParameters().Length > 0)
                        continue;
                    var setMethod = prop.GetSetMethod(false);
                    if (setMethod == null)
                        continue;
                    var attr = Attribute.GetCustomAttribute(prop, typeof(DbColumnAttribute), true) as DbColumnAttribute;
                    if (dbResult != null && dbResult.DefaultAsDbColumn)
                        if (attr != null && attr.Ignore)
                            continue;
                        else
                            attr = attr ?? new DbColumnAttribute();
                    else
                        if (attr == null || attr.Ignore)
                        continue;
                    yield return new DbColumnInfo(prop, attr);
                }
            }

            private static Converter<IDataReader, T> CreateDataLoader(List<DbColumnInfo> columnInfoes)
            {
                DynamicMethod dm = new DynamicMethod(string.Empty, typeof(T),
                    new Type[] { typeof(IDataReader) }, typeof(EntityConverter<T>));
                ILGenerator il = dm.GetILGenerator();
                LocalBuilder item = il.DeclareLocal(typeof(T));
                // [ int %index% = arg.GetOrdinal(%ColumnName%); ]
                LocalBuilder[] colIndices = GetColumnIndices(il, columnInfoes);
                // T item = new T { %Property% = ... };
                BuildItem(il, columnInfoes, item, colIndices);
                // return item;
                il.Emit(OpCodes.Ldloc_S, item);
                il.Emit(OpCodes.Ret);
                return (Converter<IDataReader, T>)dm.CreateDelegate(typeof(Converter<IDataReader, T>));
            }

            private static Converter<IDataReader, List<T>> CreateBatchDataLoader(List<DbColumnInfo> columnInfoes)
            {
                DynamicMethod dm = new DynamicMethod(string.Empty, typeof(List<T>),
                    new Type[] { typeof(IDataReader) }, typeof(EntityConverter<T>));
                ILGenerator il = dm.GetILGenerator();
                LocalBuilder list = il.DeclareLocal(typeof(List<T>));
                LocalBuilder item = il.DeclareLocal(typeof(T));
                Label exit = il.DefineLabel();
                Label loop = il.DefineLabel();
                il.Emit(OpCodes.Newobj, typeof(List<T>).GetConstructor(Type.EmptyTypes));
                il.Emit(OpCodes.Stloc_S, list);
                LocalBuilder[] colIndices = GetColumnIndices(il, columnInfoes);

                il.MarkLabel(loop);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Callvirt, DataReader_Read);
                il.Emit(OpCodes.Brfalse, exit);

                BuildItem(il, columnInfoes, item, colIndices);
                il.Emit(OpCodes.Ldloc_S, list);
                il.Emit(OpCodes.Ldloc_S, item);
                il.Emit(OpCodes.Callvirt, typeof(List<T>).GetMethod("Add"));
                il.Emit(OpCodes.Br, loop);
                il.MarkLabel(exit);
                il.Emit(OpCodes.Ldloc_S, list);
                il.Emit(OpCodes.Ret);
                return (Converter<IDataReader, List<T>>)dm.CreateDelegate(typeof(Converter<IDataReader, List<T>>));
            }

            private static LocalBuilder[] GetColumnIndices(ILGenerator il, List<DbColumnInfo> columnInfoes)
            {
                LocalBuilder[] colIndices = new LocalBuilder[columnInfoes.Count];
                for (int i = 0; i < colIndices.Length; i++)
                {
                    colIndices[i] = il.DeclareLocal(typeof(int));
                    if (columnInfoes[i].IsOptional)
                    {
                        il.BeginExceptionBlock();
                    }
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Ldstr, columnInfoes[i].ColumnName);
                    il.Emit(OpCodes.Callvirt, DataRecord_GetOrdinal);
                    il.Emit(OpCodes.Stloc_S, colIndices[i]);
                    if (columnInfoes[i].IsOptional)
                    {
                        Label exit = il.DefineLabel();
                        il.Emit(OpCodes.Leave_S, exit);
                        il.BeginCatchBlock(typeof(IndexOutOfRangeException));
                        il.Emit(OpCodes.Pop);
                        il.Emit(OpCodes.Ldc_I4_M1);
                        il.Emit(OpCodes.Stloc_S, colIndices[i]);
                        il.Emit(OpCodes.Leave_S, exit);
                        il.BeginCatchBlock(typeof(ArgumentException));
                        il.Emit(OpCodes.Pop);
                        il.Emit(OpCodes.Ldc_I4_M1);
                        il.Emit(OpCodes.Stloc_S, colIndices[i]);
                        il.Emit(OpCodes.Leave_S, exit);
                        il.EndExceptionBlock();
                        il.MarkLabel(exit);
                    }
                }
                return colIndices;
            }

            private static void BuildItem(ILGenerator il, List<DbColumnInfo> columnInfoes,
                LocalBuilder item, LocalBuilder[] colIndices)
            {
                il.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes));
                il.Emit(OpCodes.Stloc_S, item);
                Label skip = new Label();
                for (int i = 0; i < colIndices.Length; i++)
                {
                    if (columnInfoes[i].IsOptional)
                    {
                        skip = il.DefineLabel();
                        il.Emit(OpCodes.Ldloc_S, colIndices[i]);
                        il.Emit(OpCodes.Ldc_I4_M1);
                        il.Emit(OpCodes.Beq, skip);
                    }
                    if (IsCompatibleType(columnInfoes[i].Type, typeof(int)))
                    {
                        ReadInt32(il, item, columnInfoes, colIndices, i);
                    }
                    else if (IsCompatibleType(columnInfoes[i].Type, typeof(int?)))
                    {
                        ReadNullableInt32(il, item, columnInfoes, colIndices, i);
                    }
                    else if (IsCompatibleType(columnInfoes[i].Type, typeof(long)))
                    {
                        ReadInt64(il, item, columnInfoes, colIndices, i);
                    }
                    else if (IsCompatibleType(columnInfoes[i].Type, typeof(long?)))
                    {
                        ReadNullableInt64(il, item, columnInfoes, colIndices, i);
                    }
                    else if (IsCompatibleType(columnInfoes[i].Type, typeof(decimal)))
                    {
                        ReadDecimal(il, item, columnInfoes[i].SetMethod, colIndices[i]);
                    }
                    else if (columnInfoes[i].Type == typeof(decimal?))
                    {
                        ReadNullableDecimal(il, item, columnInfoes[i].SetMethod, colIndices[i]);
                    }
                    else if (columnInfoes[i].Type == typeof(float))
                    {
                        ReadFloat(il, item, columnInfoes[i].SetMethod, colIndices[i]);
                    }
                    else if (columnInfoes[i].Type == typeof(float?))
                    {
                        ReadNullableFloat(il, item, columnInfoes[i].SetMethod, colIndices[i]);
                    }
                    else if (columnInfoes[i].Type == typeof(double))
                    {
                        ReadDouble(il, item, columnInfoes[i].SetMethod, colIndices[i]);
                    }
                    else if (columnInfoes[i].Type == typeof(double?))
                    {
                        ReadNullableDouble(il, item, columnInfoes[i].SetMethod, colIndices[i]);
                    }
                    else if (columnInfoes[i].Type == typeof(DateTime))
                    {
                        ReadDateTime(il, item, columnInfoes[i].SetMethod, colIndices[i]);
                    }
                    else if (columnInfoes[i].Type == typeof(DateTime?))
                    {
                        ReadNullableDateTime(il, item, columnInfoes[i].SetMethod, colIndices[i]);
                    }
                    else
                    {
                        ReadObject(il, item, columnInfoes, colIndices, i);
                    }
                    if (columnInfoes[i].IsOptional)
                    {
                        il.MarkLabel(skip);
                    }
                }
            }

            private static bool IsCompatibleType(Type t1, Type t2)
            {
                if (t1 == t2)
                    return true;
                if (t1.IsEnum && Enum.GetUnderlyingType(t1) == t2)
                    return true;
                var u1 = Nullable.GetUnderlyingType(t1);
                var u2 = Nullable.GetUnderlyingType(t2);
                if (u1 != null && u2 != null)
                    return IsCompatibleType(u1, u2);
                return false;
            }

            private static void ReadInt32(ILGenerator il, LocalBuilder item,
                List<DbColumnInfo> columnInfoes, LocalBuilder[] colIndices, int i)
            {
                il.Emit(OpCodes.Ldloc_S, item);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc_S, colIndices[i]);
                il.Emit(OpCodes.Callvirt, DataRecord_GetInt32);
                il.Emit(OpCodes.Callvirt, columnInfoes[i].SetMethod);
            }

            private static void ReadNullableInt32(ILGenerator il, LocalBuilder item,
                List<DbColumnInfo> columnInfoes, LocalBuilder[] colIndices, int i)
            {
                var local = il.DeclareLocal(columnInfoes[i].Type);
                Label intNull = il.DefineLabel();
                Label intCommon = il.DefineLabel();
                il.Emit(OpCodes.Ldloca, local);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc_S, colIndices[i]);
                il.Emit(OpCodes.Callvirt, DataRecord_IsDBNull);
                il.Emit(OpCodes.Brtrue_S, intNull);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc_S, colIndices[i]);
                il.Emit(OpCodes.Callvirt, DataRecord_GetInt32);
                il.Emit(OpCodes.Call, columnInfoes[i].Type.GetConstructor(
                    new Type[] { Nullable.GetUnderlyingType(columnInfoes[i].Type) }));
                il.Emit(OpCodes.Br_S, intCommon);
                il.MarkLabel(intNull);
                il.Emit(OpCodes.Initobj, columnInfoes[i].Type);
                il.MarkLabel(intCommon);
                il.Emit(OpCodes.Ldloc_S, item);
                il.Emit(OpCodes.Ldloc, local);
                il.Emit(OpCodes.Callvirt, columnInfoes[i].SetMethod);
            }

            private static void ReadInt64(ILGenerator il, LocalBuilder item,
                List<DbColumnInfo> columnInfoes, LocalBuilder[] colIndices, int i)
            {
                il.Emit(OpCodes.Ldloc_S, item);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc_S, colIndices[i]);
                il.Emit(OpCodes.Callvirt, DataRecord_GetInt64);
                il.Emit(OpCodes.Callvirt, columnInfoes[i].SetMethod);
            }

            private static void ReadNullableInt64(ILGenerator il, LocalBuilder item,
                List<DbColumnInfo> columnInfoes, LocalBuilder[] colIndices, int i)
            {
                var local = il.DeclareLocal(columnInfoes[i].Type);
                Label intNull = il.DefineLabel();
                Label intCommon = il.DefineLabel();
                il.Emit(OpCodes.Ldloca, local);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc_S, colIndices[i]);
                il.Emit(OpCodes.Callvirt, DataRecord_IsDBNull);
                il.Emit(OpCodes.Brtrue_S, intNull);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc_S, colIndices[i]);
                il.Emit(OpCodes.Callvirt, DataRecord_GetInt64);
                il.Emit(OpCodes.Call, columnInfoes[i].Type.GetConstructor(
                    new Type[] { Nullable.GetUnderlyingType(columnInfoes[i].Type) }));
                il.Emit(OpCodes.Br_S, intCommon);
                il.MarkLabel(intNull);
                il.Emit(OpCodes.Initobj, columnInfoes[i].Type);
                il.MarkLabel(intCommon);
                il.Emit(OpCodes.Ldloc_S, item);
                il.Emit(OpCodes.Ldloc, local);
                il.Emit(OpCodes.Callvirt, columnInfoes[i].SetMethod);
            }

            private static void ReadDecimal(ILGenerator il, LocalBuilder item,
                MethodInfo setMethod, LocalBuilder colIndex)
            {
                il.Emit(OpCodes.Ldloc_S, item);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc_S, colIndex);
                il.Emit(OpCodes.Callvirt, DataRecord_GetDecimal);
                il.Emit(OpCodes.Callvirt, setMethod);
            }

            private static void ReadNullableDecimal(ILGenerator il, LocalBuilder item,
                MethodInfo setMethod, LocalBuilder colIndex)
            {
                var local = il.DeclareLocal(typeof(decimal?));
                Label decimalNull = il.DefineLabel();
                Label decimalCommon = il.DefineLabel();
                il.Emit(OpCodes.Ldloca, local);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc_S, colIndex);
                il.Emit(OpCodes.Callvirt, DataRecord_IsDBNull);
                il.Emit(OpCodes.Brtrue_S, decimalNull);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc_S, colIndex);
                il.Emit(OpCodes.Callvirt, DataRecord_GetDecimal);
                il.Emit(OpCodes.Call, typeof(decimal?).GetConstructor(new Type[] { typeof(decimal) }));
                il.Emit(OpCodes.Br_S, decimalCommon);
                il.MarkLabel(decimalNull);
                il.Emit(OpCodes.Initobj, typeof(decimal?));
                il.MarkLabel(decimalCommon);
                il.Emit(OpCodes.Ldloc_S, item);
                il.Emit(OpCodes.Ldloc, local);
                il.Emit(OpCodes.Callvirt, setMethod);
            }
            
            private static void ReadFloat(ILGenerator il, LocalBuilder item,
                MethodInfo setMethod, LocalBuilder colIndex)
            {
                il.Emit(OpCodes.Ldloc_S, item);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc_S, colIndex);
                il.Emit(OpCodes.Callvirt, DataRecord_GetFloat);
                il.Emit(OpCodes.Callvirt, setMethod);
            }

            private static void ReadNullableFloat(ILGenerator il, LocalBuilder item,
               MethodInfo setMethod, LocalBuilder colIndex)
            {
                var local = il.DeclareLocal(typeof(float?));
                Label decimalNull = il.DefineLabel();
                Label decimalCommon = il.DefineLabel();
                il.Emit(OpCodes.Ldloca, local);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc_S, colIndex);
                il.Emit(OpCodes.Callvirt, DataRecord_IsDBNull);
                il.Emit(OpCodes.Brtrue_S, decimalNull);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc_S, colIndex);
                il.Emit(OpCodes.Callvirt, DataRecord_GetFloat);
                il.Emit(OpCodes.Call, typeof(float?).GetConstructor(new Type[] { typeof(float) }));
                il.Emit(OpCodes.Br_S, decimalCommon);
                il.MarkLabel(decimalNull);
                il.Emit(OpCodes.Initobj, typeof(float?));
                il.MarkLabel(decimalCommon);
                il.Emit(OpCodes.Ldloc_S, item);
                il.Emit(OpCodes.Ldloc, local);
                il.Emit(OpCodes.Callvirt, setMethod);
            }

            private static void ReadDouble(ILGenerator il, LocalBuilder item,
                MethodInfo setMethod, LocalBuilder colIndex)
            {
                il.Emit(OpCodes.Ldloc_S, item);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc_S, colIndex);
                il.Emit(OpCodes.Callvirt, DataRecord_GetDouble);
                il.Emit(OpCodes.Callvirt, setMethod);
            }

            private static void ReadNullableDouble(ILGenerator il, LocalBuilder item,
               MethodInfo setMethod, LocalBuilder colIndex)
            {
                var local = il.DeclareLocal(typeof(double?));
                Label decimalNull = il.DefineLabel();
                Label decimalCommon = il.DefineLabel();
                il.Emit(OpCodes.Ldloca, local);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc_S, colIndex);
                il.Emit(OpCodes.Callvirt, DataRecord_IsDBNull);
                il.Emit(OpCodes.Brtrue_S, decimalNull);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc_S, colIndex);
                il.Emit(OpCodes.Callvirt, DataRecord_GetDouble);
                il.Emit(OpCodes.Call, typeof(double?).GetConstructor(new Type[] { typeof(double) }));
                il.Emit(OpCodes.Br_S, decimalCommon);
                il.MarkLabel(decimalNull);
                il.Emit(OpCodes.Initobj, typeof(double?));
                il.MarkLabel(decimalCommon);
                il.Emit(OpCodes.Ldloc_S, item);
                il.Emit(OpCodes.Ldloc, local);
                il.Emit(OpCodes.Callvirt, setMethod);
            }

            private static void ReadDateTime(ILGenerator il, LocalBuilder item,
                MethodInfo setMethod, LocalBuilder colIndex)
            {
                il.Emit(OpCodes.Ldloc_S, item);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc_S, colIndex);
                il.Emit(OpCodes.Callvirt, DataRecord_GetDateTime);
                il.Emit(OpCodes.Callvirt, setMethod);
            }

            private static void ReadNullableDateTime(ILGenerator il, LocalBuilder item,
                MethodInfo setMethod, LocalBuilder colIndex)
            {
                var local = il.DeclareLocal(typeof(DateTime?));
                Label dtNull = il.DefineLabel();
                Label dtCommon = il.DefineLabel();
                il.Emit(OpCodes.Ldloca, local);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc_S, colIndex);
                il.Emit(OpCodes.Callvirt, DataRecord_IsDBNull);
                il.Emit(OpCodes.Brtrue_S, dtNull);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc_S, colIndex);
                il.Emit(OpCodes.Callvirt, DataRecord_GetDateTime);
                il.Emit(OpCodes.Call, typeof(DateTime?).GetConstructor(new Type[] { typeof(DateTime) }));
                il.Emit(OpCodes.Br_S, dtCommon);
                il.MarkLabel(dtNull);
                il.Emit(OpCodes.Initobj, typeof(DateTime?));
                il.MarkLabel(dtCommon);
                il.Emit(OpCodes.Ldloc_S, item);
                il.Emit(OpCodes.Ldloc, local);
                il.Emit(OpCodes.Callvirt, setMethod);
            }

            private static void ReadObject(ILGenerator il, LocalBuilder item,
                List<DbColumnInfo> columnInfoes, LocalBuilder[] colIndices, int i)
            {
                Label common = il.DefineLabel();
                il.Emit(OpCodes.Ldloc_S, item);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldloc_S, colIndices[i]);
                il.Emit(OpCodes.Callvirt, DataRecord_ItemGetter_Int);
                il.Emit(OpCodes.Dup);
                il.Emit(OpCodes.Call, Convert_IsDBNull);
                il.Emit(OpCodes.Brfalse_S, common);
                il.Emit(OpCodes.Pop);
                il.Emit(OpCodes.Ldnull);
                il.MarkLabel(common);
                il.Emit(OpCodes.Unbox_Any, columnInfoes[i].Type);
                il.Emit(OpCodes.Callvirt, columnInfoes[i].SetMethod);
            }
            #endregion

            #region Internal Methods
            internal static IEnumerable<T> SelectDelay(IDataReader reader)
            {
                while (reader.Read())
                    yield return DataLoader(reader);
            }

            internal static List<T> Select(IDataReader reader)
            {
                return BatchDataLoader(reader);
            }
            #endregion
        }
        #endregion
    }
}

数据库连接类
抽象类:

using DBExtensions;
using System;
using System.Collections.Generic;
using System.Data;

namespace DAL
{
    public abstract class BasicDataAccess
    {
        protected IDbConnection conn = null;
        
        #region protected Method
        public T ExecuteScalar<T>(string sql, Dictionary<string, object> parameters = null)
        {
            T Result = (T)Convert.ChangeType(ExecuteScalar(sql,parameters), typeof(T));
            return Result;
        }
        /// <summary>
        /// 返回select语句唯一值,
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public dynamic ExecuteScalar(string sql, Dictionary<string, object> parameters = null)
        {
            Open();
            IDbCommand command = GetCmd();
            command.CommandType = CommandType.Text;
            command.CommandText = sql;

            SetParameter(command, parameters);

            dynamic result = command.ExecuteScalar();
            Close();
            return result;
        }
        /// <summary>
        /// 返回影响行数,处理非select语句
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public int ExecuteNonQuery(string sql, Dictionary<string, object> parameters = null)
        {
            Open();
            IDbCommand command = GetCmd();
            command.CommandType = CommandType.Text;
            command.CommandText = sql;

            SetParameter(command, parameters);

            int nR = command.ExecuteNonQuery();
            Close();
            return nR;
        }

        public int ExecuteNonQuery(string sql, List<DBTypeExt> DBType, Dictionary<string, object> parameters = null)
        {
            Open();
            IDbCommand command = GetCmd();
            command.CommandType = CommandType.Text;
            command.CommandText = sql;

            SetParameter(command, DBType, parameters);

            int nR = command.ExecuteNonQuery();
            Close();
            return nR;
        }

        public List<T> Query<T>(string strSql, Dictionary<string, object> parameters = null) where T : class, new()
        {
            Open();
            IDbCommand command = GetCmd();
            command.CommandType = CommandType.Text;
            command.CommandText = strSql;

            SetParameter(command, parameters);

            IDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection);
            List<T> result = reader.Select<T>();
            Close();
            return result;
        }

        public IDataReader GetDataReader(string strSql, Dictionary<string, object> parameters = null)
        {
            IDataReader reader = null;
            try
            {
                Open();
                IDbCommand command = GetCmd();
                command.CommandType = CommandType.Text;
                command.CommandText = strSql;

                SetParameter(command, parameters);
                reader = command.ExecuteReader(CommandBehavior.CloseConnection);
            }
            catch
            {
                Close();
                throw;
            }
            return reader;
        }

        #endregion

        #region 抽象方法
        public abstract void Open();
        protected abstract void SetParameter(IDbCommand command, Dictionary<string, object> parameters);
        protected abstract void SetParameter(IDbCommand command, List<DBTypeExt> DbTypes, Dictionary<string, object> parameters);
        protected abstract IDbDataAdapter GetDataAdapter(IDbCommand command);
        #endregion

        #region GetDataTable
        public DataTable GetDataTable(string strSql, Dictionary<string, object> parameters=null)
        {
            DataSet dataSet = new DataSet();
            IDbCommand command = null;

            try
            {
                Open();
                command = GetCmd();
                command.CommandType = CommandType.Text;
                command.CommandText = strSql;

                SetParameter(command, parameters);
                IDataAdapter adapter = GetDataAdapter(command);

                adapter.Fill(dataSet);
                return dataSet.Tables[0];
            }
            catch (Exception ex)
            {
                dataSet.Clear();
                throw ex;
            }
            finally
            {
                command.Dispose();
                Close();
            }
        }

        /// <summary>
        /// </summary>
        /// <param name="sqls"></param>
        /// <param name="nErrI"></param>
        /// <returns></returns>
        public bool DB_Transaction(List<String> sqls, ref int nErrI,ref string strErr)
        {
            IDbCommand command = null;
            try
            {
                Open();
                IDbConnection conn = GetConn();
                command = GetCmd();
                command.Transaction = conn.BeginTransaction();
                nErrI = 0;

                foreach (string sql in sqls)
                {
                    command.CommandText = sql;
                    command.ExecuteNonQuery();
                    nErrI++;
                }
                command.Transaction.Commit();
                return true;
            }
            catch (Exception e)
            {
                if (command.Transaction != null)
                {
                    command.Transaction.Rollback();//回滚事务                    
                }
                strErr = e.Message;
            }
            finally
            {
                command.Dispose();
                Close();
            }
            return false;
        }

        public bool DB_Transaction(List<sqlParameter> sqls, ref int nErrI, ref string strErr)
        {
            IDbCommand command = null;
            try
            {
                Open();
                IDbConnection conn = GetConn();
                command = GetCmd();
                command.Transaction = conn.BeginTransaction();
                nErrI = 0;

                foreach (sqlParameter item in sqls)
                {
                    command.CommandType = CommandType.Text;
                    command.CommandText = item.sql;
                    command.Parameters.Clear();

                    SetParameter(command, item.paramTypes, item.dictParams);
                    command.ExecuteNonQuery();
                    nErrI++;
                }
                command.Transaction.Commit();
                return true;
            }
            catch (Exception e)
            {
                if (command.Transaction != null)
                {
                    command.Transaction.Rollback();                   
                }
                strErr = e.Message;
            }
            finally
            {
                command.Dispose();
                Close();
            }
            return false;
        }
        #endregion

        #region 受保护方法GetConn(),GetCmd(),Close()
        protected IDbConnection GetConn()
        {
            return conn;
        }

        protected IDbCommand GetCmd()
        {
            return conn.CreateCommand();
        }

        public void Close()
        {
            if (conn != null && conn.State == ConnectionState.Open)
            {
                try
                {
                    conn.Close();
                    conn = null;
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }
        #endregion
    }
}

oracle子类

using System;
using System.Data;
using Oracle.ManagedDataAccess.Client;
using System.Collections.Generic;
using DBExtensions;

namespace DAL
{
    /// <summary>
    /// 1.目前此类不支持以参数形式insert update select操作BLOB字段不太好;
    /// 2.此类不打算支持short、byte、bool类型字段;
    /// </summary>
    public class OracleDataAccess : BasicDataAccess, IDisposable
    {
        private string _strConn = string.Empty;
        public OracleDataAccess()
        {
            _strConn = System.Configuration.ConfigurationManager.ConnectionStrings["conn"].ToString();
        }

        public OracleDataAccess(string strConn)
        {
            _strConn = strConn;
        }

        public override void Open()
        {
            try
            {
                if (conn == null)
                {
                    conn = new OracleConnection(_strConn);
                }

                if (conn.State != ConnectionState.Open)
                    conn.Open();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        protected override IDbDataAdapter GetDataAdapter(IDbCommand command)
        {
            IDbDataAdapter dbadapter = new OracleDataAdapter((OracleCommand)command);
            return dbadapter;
        }

        protected override void SetParameter(IDbCommand command, Dictionary<string, object> parameters)
        {
            if (parameters == null)
                return;

            foreach (KeyValuePair<string, object> kvp in parameters)
            {
                OracleParameter p = new OracleParameter(kvp.Key, kvp.Value);
                command.Parameters.Add(p);
            }
        }

        protected override void SetParameter(IDbCommand command, List<DBTypeExt> DBTypes, Dictionary<string, object> parameters)
        {
            if (parameters == null)
                return;

            int nIndex = 0;
            foreach (KeyValuePair<string, object> kvp in parameters)
            {
                OracleParameter p = new OracleParameter(kvp.Key, (OracleDbType)DBTypes[nIndex], kvp.Value, ParameterDirection.Input);
                command.Parameters.Add(p);
                nIndex++;
            }
        }

        public void Dispose()
        {
            Close();
        }
    }
}

db扩展:
DBExtensions类

using System;

namespace DBExtensions
{
    /// <summary>
    /// 标示该属性是(或不是)数据列
    /// </summary>
    [AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
    public sealed class DbColumnAttribute : Attribute
    {
        /// <summary>
        /// 列名(缺省时使用属性名)
        /// </summary>
        public string ColumnName { get; set; }

        /// <summary>
        /// 是否强制忽略该属性
        /// </summary>
        public bool Ignore { get; set; }

        /// <summary>
        /// 可选数据列(Reader中不存在该列时,保持默认值)
        /// </summary>
        public bool IsOptional { get; set; }
    }

    /// <summary>
    /// 标示该类为数据库的结果集实体
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
    public sealed class DbResultAttribute : Attribute
    {
        /// <summary>
        /// 默认所有属性是数据列
        /// </summary>
        public DbResultAttribute()
            : this(true) { }

        /// <summary>
        /// 默认所有属性是(或不是)数据列
        /// </summary>
        /// <param name="defaultAsDbColumn">默认是数据列</param>
        public DbResultAttribute(bool defaultAsDbColumn)
        {
            DefaultAsDbColumn = defaultAsDbColumn;
        }

        /// <summary>
        /// 默认是数据列
        /// </summary>
        public bool DefaultAsDbColumn { get; private set; }
    }
}

表模型attribute

using System;


namespace DBExtensions
{
    [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
    public sealed class DBEntityAttribute : Attribute
    {
        /// <summary>
        /// 表名或者视图名,或者是作为视图的sql语句
        /// </summary>
        public string EntityName { set; get; }

        /// <summary>
        /// 主键
        /// </summary>
        public string EntityPK { set; get; }

        /// <summary>
        /// 是否有大字段(geom、clob)
        /// </summary>
        public bool haveLargeField { set; get;}

        /// <summary>
        /// 对应数据库字段参数类型
        /// </summary>
        public DBTypeExt[] ParamTypes { set; get; }
    }


    [AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = true)]
    public sealed class DBDetailAttribute : Attribute
    {
        /// <summary>
        /// 是否CLOB字段
        /// </summary>
        public bool ClobField { set; get; }

        /// <summary>
        /// 是否GEOM字段
        /// </summary>
        public bool GeomField { set; get; }
    }
}

数据库参数类型扩展

using System.Collections.Generic;

namespace DBExtensions
{
    public enum DBTypeExt
    {
        orclBFile = 101,
        orclBlob = 102,
        orclByte = 103,
        orclChar = 104,
        orclClob = 105,
        orclDate = 106,
        orclDecimal = 107,
        orclDouble = 108,
        orclLong = 109,
        orclLongRaw = 110,
        orclInt16 = 111,
        orclInt32 = 112,
        orclInt64 = 113,
        orclIntervalDS = 114,
        orclIntervalYM = 115,
        orclNClob = 116,
        orclNChar = 117,
        orclNVarchar2 = 119,
        orclRaw = 120,
        orclRefCursor = 121,
        orclSingle = 122,
        orclTimeStamp = 123,
        orclTimeStampLTZ = 124,
        orclTimeStampTZ = 125,
        orclVarchar2 = 126,
        orclXmlType = 127,
        orclBinaryDouble = 132,
        orclBinaryFloat = 133
    }
    
    public struct sqlParameter
    {
        public string sql;
        public Dictionary<string, object> dictParams;
        public List<DBTypeExt> paramTypes;

        public sqlParameter(string s, Dictionary<string, object> ps, List<DBTypeExt> ts)
        {
            sql = s;
            dictParams = ps;
            paramTypes = ts;
        }
    }
}

第二部分
vs 2015 轻量级orm框架(二)付源码及测试用例

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值