using System.Collections.Generic;
using System.Data;
using System.Linq;
using Dapper;
using DapperExtensions;
using Mall.DataAccess;
using Mall.DataAccess.Utils;
using Mall.DataHelper;
using System.Text;
using DapperExtensions.Lambda;
using System;
using Mall.Common.AOP;
using System.Transactions;

namespace Mall.Repository
{
    /// <summary>
    /// Repository基类
    /// </summary>
    public class RepositoryBase<T> : ILambdaHelper<T>, IDataRepository<T> where T : class
    {
        /// <summary>
        /// DB
        /// </summary>
        public IDBSession DBSession;

        /// <summary>
        /// 创建事务对象[仅支持同一数据库事务操作]
        /// </summary>
        public IDbTransaction DbTransaction
        {
            get
            {
                this.DBSession = new DBSessionBase(new Database(ConnKey));
                this.DBSession.Connection.Open();
                DBSession.Transaction = this.DBSession.Connection.BeginTransaction();
                return DBSession.Transaction;
            }
        }

        /// <summary>
        /// 链接字符串
        /// </summary>
        public string ConnKey { get; private set; }

        #region 构造函数
        /// <summary>
        /// 构造函数重写ConnKey获取方法
        /// </summary>
        /// <param name="connKey">连接字符串Key</param>
        public RepositoryBase(string connKey = "DefaultConnection")
        {
            try
            {
                var classAttribute = (DBAttribute)Attribute.GetCustomAttribute(typeof(T), typeof(DBAttribute));
                connKey = classAttribute.ConnectionName ?? "DefaultConnection";
            }
            catch (Exception ex)
            {
                throw ex;
            }
            ConnKey = connKey;
        }

        #endregion

        #region Execute

        /// <summary>
        /// 执行sql操作[增、删、改]
        /// </summary>
        /// <param name="sql">sql命令</param>
        /// <param name="param">动态参数</param>
        /// <param name="transaction">事务对象</param>
        /// <param name="commandTimeout">超时时间</param>
        /// <param name="commandType">命令类型</param>
        /// <returns></returns>
        public int Execute(string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            DbConnObj ConnObj = GetConnObj(transaction);
            if (ConnObj.DbConnection != null)
            {
                return ConnObj.DbConnection.Execute(sql, param as object, ConnObj.DbTransaction, commandTimeout, commandType);
            }
            else
            {
                using (IDbConnection conn = DBUtils.CreateDBConnection(ConnKey, out DataBaseType dbType))
                {
                    return conn.Execute(sql, param as object, ConnObj.DbTransaction, commandTimeout, commandType);
                }
            }
        }
        #endregion

        #region ExecuteScalar
        /// <summary>
        /// 返回第一行第一列
        /// </summary>
        /// <param name="sql">sql命令</param>
        /// <param name="param">动态参数</param>
        /// <param name="transaction">事务对象</param>
        /// <param name="commandTimeout">超时时间</param>
        /// <param name="commandType">命令类型</param>
        /// <returns></returns>
        public object ExecuteScalar(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            DbConnObj ConnObj = GetConnObj(transaction);
            if (ConnObj.DbConnection != null)
            {
                return ConnObj.DbConnection.ExecuteScalar(sql, param as object, ConnObj.DbTransaction, commandTimeout, commandType);
            }
            else
            {
                using (IDbConnection conn = DBUtils.CreateDBConnection(ConnKey, out DataBaseType dbType))
                {
                    return conn.ExecuteScalar(sql, param as object, ConnObj.DbTransaction, commandTimeout, commandType);
                }
            }
        }
        #endregion

        #region Insert

        /// <summary>
        /// 新增一条数据
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns></returns>
        public dynamic Insert(T entity)
        {
            DbConnObj ConnObj = GetConnObj();
            if (ConnObj.DbConnection != null)
            {
                return ConnObj.DbConnection.Insert<T>(entity, ConnObj.DbTransaction, dbType: ConnObj.DbType);
            }
            else
            {
                using (IDbConnection conn = DBUtils.CreateDBConnection(ConnKey, out DataBaseType dbType))
                {
                    return conn.Insert<T>(entity, ConnObj.DbTransaction, dbType: dbType);
                }
            }
        }

        /// <summary>
        /// 新增一条数据(带事务)
        /// </summary>
        /// <param name="entity">实体</param>
        /// <param name="tran">事务对象</param>
        /// <returns></returns>
        public dynamic Insert(T entity, IDbTransaction tran)
        {
            DbConnObj ConnObj = GetConnObj(tran);
            if (ConnObj.DbConnection != null)
            {
                return ConnObj.DbConnection.Insert<T>(entity, ConnObj.DbTransaction, dbType: ConnObj.DbType);
            }
            else
            {
                using (IDbConnection conn = DBUtils.CreateDBConnection(this.ConnKey, out DataBaseType dbType))
                {
                    return conn.Insert<T>(entity, ConnObj.DbTransaction, dbType: dbType);
                }
            }
        }

        /// <summary>
        /// 批量插入功能
        /// </summary>
        /// <param name="entityList">实体集合</param>
        /// <param name="transaction">事务对象</param>
        public bool InsertBatch(IEnumerable<T> entityList, IDbTransaction transaction = null)
        {
            bool isOk = false;
            foreach (var item in entityList)
            {
                Insert(item, transaction);
            }
            isOk = true;
            return isOk;
        }

        #endregion

        #region Update
        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="entity">实体</param>
        /// <param name="transaction">事务对象</param>
        /// <returns></returns>
        public bool Update(T entity, IDbTransaction transaction = null)
        {
            DbConnObj ConnObj = GetConnObj(transaction);
            if (ConnObj.DbConnection != null)
            {
                return ConnObj.DbConnection.Update<T>(entity, ConnObj.DbTransaction, dbType: ConnObj.DbType);
            }
            else
            {
                using (IDbConnection conn = DBUtils.CreateDBConnection(ConnKey, out DataBaseType dbType))
                {
                    return conn.Update<T>(entity, ConnObj.DbTransaction, dbType: dbType);
                }
            }
        }

        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="fileds">需要更新的字段</param>
        /// <param name="whereHelpers">where条件</param>
        /// <param name="transaction">事务</param>
        /// <returns></returns>
        public bool Update(IDictionary<string, object> fileds, IList<WhereHelper> whereHelpers, IDbTransaction transaction = null)
        {
            string tableName = typeof(T).Name;
            StringBuilder sb = new StringBuilder();
            if (fileds != null && whereHelpers != null)
            {
                sb.Append(string.Format(@"UPDATE {0} SET ", tableName));
                string setStr = string.Empty;
                var parameters = new DynamicParameters();
                foreach (var item in fileds)
                {
                    setStr += string.Format(@",`{0}`=@{0} ", item.Key);
                    parameters.Add(item.Key, item.Value);
                }
                sb.Append(setStr.Substring(1));
                sb.Append(" WHERE 1=1 ");
                foreach (var item in whereHelpers)
                {
                    switch (item.OperatorEnum)
                    {
                        case OperatorEnum.Equal:
                            sb.AppendFormat(@" AND {0}=@D{0}", item.FiledName);
                            break;
                        case OperatorEnum.NotEqual:
                            sb.AppendFormat(@" AND {0}<>@D{0}", item.FiledName);
                            break;
                    }
                    parameters.Add("D" + item.FiledName, item.FiledValue);
                }
                return this.Execute(sb.ToString(), parameters, transaction) > 0;
            }
            else
            {
                throw new System.Exception("keyValues不能为空!");
            }
        }

        /// <summary>
        /// 更新数据库字段(单个条件)
        /// </summary>
        /// <param name="fileds">更新字段(字典)</param>
        /// <param name="whereHelper">where条件(单个)</param>
        /// <param name="transaction">事务对象</param>
        /// <returns></returns>
        public bool Update(IDictionary<string, object> fileds, WhereHelper whereHelper, IDbTransaction transaction = null)
        {
            string tableName = typeof(T).Name;
            StringBuilder sb = new StringBuilder();
            if (fileds != null && whereHelper != null)
            {
                sb.Append(string.Format(@"UPDATE {0} SET ", tableName));
                string setStr = string.Empty;
                var parameters = new DynamicParameters();
                foreach (var item in fileds)
                {
                    setStr += string.Format(@",{0}=@{0} ", item.Key);
                    parameters.Add(item.Key, item.Value);
                }
                sb.Append(setStr.Substring(1));
                sb.Append(" WHERE 1=1 ");
                switch (whereHelper.OperatorEnum)
                {
                    case OperatorEnum.Equal:
                        sb.AppendFormat(@" AND {0}=@D{0}", whereHelper.FiledName);
                        break;
                    case OperatorEnum.NotEqual:
                        sb.AppendFormat(@" AND {0}<>@D{0}", whereHelper.FiledName);
                        break;
                }
                parameters.Add("D" + whereHelper.FiledName, whereHelper.FiledValue);
                var flag= this.Execute(sb.ToString(), parameters, transaction) > 0;
                return flag;
            }
            else
            {
                throw new System.Exception("keyValues不能为空!");
            }

        }

        /// <summary>
        /// 批量更新数据
        /// </summary>
        /// <param name="entityList">实体列表对象</param>
        /// <param name="transaction">事务对象</param>
        /// <returns></returns>
        public bool UpdateBatch(IEnumerable<T> entityList, IDbTransaction transaction = null)
        {
            bool isOk = false;
            foreach (var item in entityList)
            {
                Update(item, transaction);
            }
            isOk = true;
            return isOk;
        }
        #endregion

        #region Delete

        /// <summary>
        /// 删除数据
        /// </summary>
        /// <param name="primaryId">主键编号</param>
        /// <param name="transaction">事务对象</param>
        /// <returns></returns>
        public int Delete(dynamic primaryId, IDbTransaction transaction = null)
        {
            DbConnObj ConnObj = GetConnObj(transaction);
            if (ConnObj.DbConnection != null)
            {
                object entity = this.GetEntity(primaryId);
                var obj = entity as T;
                return ConnObj.DbConnection.Delete<T>(obj, ConnObj.DbTransaction, dbType: ConnObj.DbType);
            }
            else
            {
                using (IDbConnection conn = DBUtils.CreateDBConnection(ConnKey, out DataBaseType dbType))
                {
                    object entity = conn.Get<T>(primaryId as object, ConnObj.DbTransaction, dbType: dbType);
                    var obj = entity as T;
                    return conn.Delete<T>(obj, ConnObj.DbTransaction, dbType: dbType);
                }
            }
        }

        /// <summary>
        /// 根据字典删除数据
        /// </summary>
        /// <param name="whereHelpers">删除条件字典</param>
        /// <param name="transaction">事务对象</param>
        /// <returns></returns>
        public bool Delete(IList<WhereHelper> whereHelpers, IDbTransaction transaction = null)
        {
            StringBuilder sb = new StringBuilder();
            if (whereHelpers != null)
            {
                sb.Append(string.Format(@"DELETE FROM {0} WHERE 1=1 ", typeof(T).Name));
                var parameters = new DynamicParameters();
                foreach (var item in whereHelpers)
                {
                    switch (item.OperatorEnum)
                    {
                        case OperatorEnum.Equal:
                            sb.AppendFormat(@" AND {0}=@D{0}", item.FiledName);
                            break;
                        case OperatorEnum.NotEqual:
                            sb.AppendFormat(@" AND {0}<>@D{0}", item.FiledName);
                            break;
                    }
                    parameters.Add("D" + item.FiledName, item.FiledValue);
                }

                return this.Execute(sb.ToString(), parameters, transaction) > 0;
            }
            else
            {
                throw new System.Exception("keyValues不能为空!");
            }
        }

        /// <summary>
        /// 根据Where条件删除一条记录
        /// </summary>
        /// <param name="whereHelper">删除条件字典</param>
        /// <param name="transaction">事务对象</param>
        /// <returns></returns>
        public bool DeleteOne(WhereHelper whereHelper, IDbTransaction transaction = null)
        {
            StringBuilder sb = new StringBuilder();
            if (whereHelper != null)
            {
                sb.Append(string.Format(@"DELETE FROM {0} WHERE 1=1 ", typeof(T).Name));
                var parameters = new DynamicParameters();

                switch (whereHelper.OperatorEnum)
                {
                    case OperatorEnum.Equal:
                        sb.AppendFormat(@" AND {0}=@D{0}", whereHelper.FiledName);
                        break;
                    case OperatorEnum.NotEqual:
                        sb.AppendFormat(@" AND {0}<>@D{0}", whereHelper.FiledName);
                        break;
                }
                parameters.Add("D" + whereHelper.FiledName, whereHelper.FiledValue);
                return this.Execute(sb.ToString(), parameters, transaction) > 0;
            }
            else
            {
                throw new System.Exception("keyValues不能为空!");
            }
        }

        /// <summary>
        ///根据条件 批量删除数据
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="transaction">事务对象</param>
        /// <returns></returns>
        public int DeleteList(object predicate, IDbTransaction transaction = null)
        {
            DbConnObj ConnObj = GetConnObj(transaction);
            if (ConnObj.DbConnection != null)
            {
                return ConnObj.DbConnection.Delete<T>(predicate, ConnObj.DbTransaction, dbType: ConnObj.DbType);
            }
            else
            {
                using (IDbConnection conn = DBUtils.CreateDBConnection(ConnKey, out DataBaseType dbType))
                {
                    return conn.Delete<T>(predicate, ConnObj.DbTransaction, dbType: dbType);
                }
            }
        }

        /// <summary>
        /// 根据主键列表 批量删除数据
        /// </summary>
        /// <param name="ids">编号</param>
        /// <param name="transaction">事务对象</param>
        /// <returns></returns>
        public bool DeleteBatch(IEnumerable<dynamic> ids, IDbTransaction transaction = null)
        {
            bool isOk = false;
            foreach (var id in ids)
            {
                this.Delete(id, transaction);
            }
            isOk = true;
            return isOk;
        }

        #endregion

        #region Exists

        /// <summary>
        /// 判断表中是否存在记录
        /// </summary>
        /// <param name="whereHelpers">条件</param>
        /// <param name="transaction">事务对象</param>
        /// <returns></returns>
        public bool Exists(IList<WhereHelper> whereHelpers, IDbTransaction transaction = null)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat(" SELECT 1 FROM {0} WHERE 1=1 ", typeof(T).Name);
            if (whereHelpers != null)
            {
                var parameters = new DynamicParameters();
                foreach (var item in whereHelpers)
                {
                    switch (item.OperatorEnum)
                    {
                        case OperatorEnum.Equal:
                            sb.AppendFormat(@" AND {0}=@D{0}", item.FiledName);
                            break;
                        case OperatorEnum.NotEqual:
                            sb.AppendFormat(@" AND {0}<>@D{0}", item.FiledName);
                            break;
                        case OperatorEnum.MoreThan:
                            sb.AppendFormat(@" AND {0}>@D{0}", item.FiledName);
                            break;
                        case OperatorEnum.MoreThanEqual:
                            sb.AppendFormat(@" AND {0}>=@D{0}", item.FiledName);
                            break;
                        case OperatorEnum.LessThan:
                            sb.AppendFormat(@" AND {0}<@D{0}", item.FiledName);
                            break;
                        case OperatorEnum.LessThanEqual:
                            sb.AppendFormat(@" AND {0}<=@D{0}", item.FiledName);
                            break;
                    }
                    parameters.Add("D" + item.FiledName, item.FiledValue);
                }
                sb.Append(" limit 1; ");
                DbConnObj ConnObj = GetConnObj();
                object obj = ExecuteScalar(sb.ToString(), parameters, transaction);
                if (obj != null && Convert.ToInt32(obj) > 0)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                throw new System.Exception("keyValues不能为空!");
            }
        }

        /// <summary>
        /// 判断表中是否存在记录
        /// </summary>
        /// <param name="keyFiled">主键字段</param>
        /// <param name="whereHelpers">条件</param>
        /// <param name="transaction">事务对象</param>
        /// <returns></returns>
        public int Exists(string keyFiled, IList<WhereHelper> whereHelpers, IDbTransaction transaction = null)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat(" SELECT {0} FROM {1} WHERE 1=1 ", keyFiled, typeof(T).Name);
            if (whereHelpers != null)
            {
                var parameters = new DynamicParameters();
                foreach (var item in whereHelpers)
                {
                    switch (item.OperatorEnum)
                    {
                        case OperatorEnum.Equal:
                            sb.AppendFormat(@" AND {0}=@D{0}", item.FiledName);
                            break;
                        case OperatorEnum.NotEqual:
                            sb.AppendFormat(@" AND {0}<>@D{0}", item.FiledName);
                            break;
                    }
                    parameters.Add("D" + item.FiledName, item.FiledValue);
                }
                sb.Append(" limit 1; ");
                DbConnObj ConnObj = GetConnObj();
                object obj = ExecuteScalar(sb.ToString(), parameters, transaction);
                if (obj != null && Convert.ToInt32(obj) > 0)
                {
                    return Convert.ToInt32(obj);
                }
                else
                {
                    return 0;
                }
            }
            else
            {
                throw new System.Exception("keyValues不能为空!");
            }
        }

        #endregion

        #region GetEntity

        /// <summary>
        /// 根据主键获得实体对象
        /// </summary>
        /// <param name="primaryId">主键编号</param>
        /// <returns></returns>
        public T GetEntity(dynamic primaryId)
        {
            DbConnObj ConnObj = GetConnObj();
            if (ConnObj.DbConnection != null)
            {
                return ConnObj.DbConnection.Get<T>(primaryId as object, ConnObj.DbTransaction, dbType: ConnObj.DbType);
            }
            else
            {
                using (IDbConnection conn = DBUtils.CreateDBConnection(ConnKey, out DataBaseType dbType))
                {
                    return conn.Get<T>(primaryId as object, ConnObj.DbTransaction, dbType: dbType);
                }
            }
        }

        /// <summary>
        /// 根据主键获得实体对象
        /// </summary>
        /// <typeparam name="TReturn">类型</typeparam>
        /// <param name="primaryId">主键编号</param>
        /// <returns></returns>
        public TReturn GetEntity<TReturn>(dynamic primaryId) where TReturn : class
        {
            DbConnObj ConnObj = GetConnObj();
            if (ConnObj.DbConnection != null)
            {
                return ConnObj.DbConnection.Get<T, TReturn>(primaryId as object, ConnObj.DbTransaction, dbType: ConnObj.DbType);
            }
            else
            {
                using (IDbConnection conn = DBUtils.CreateDBConnection(ConnKey, out DataBaseType dbType))
                {
                    return conn.Get<T, TReturn>(primaryId as object, ConnObj.DbTransaction, dbType: dbType);
                }
            }
        }
        #endregion

        #region GetList

        /// <summary>
        /// 根据主键列表 获得实体对象集合
        /// </summary>
        /// <param name="ids">动态Id</param>
        /// <returns></returns>
        public IEnumerable<T> GetList(IList<dynamic> ids)
        {
            var tblName = string.Format("dbo.{0}", typeof(T).Name);
            var idsin = string.Join(",", ids.ToArray<dynamic>());
            var sql = "SELECT * FROM @table WHERE Id in (@ids)";
            DbConnObj ConnObj = GetConnObj();
            IEnumerable<T> dataList = new List<T>();
            if (ConnObj.DbConnection != null)
            {
                dataList = ConnObj.DbConnection.Query<T>(sql, new { table = tblName, ids = idsin }, ConnObj.DbTransaction);
            }
            else
            {
                using (IDbConnection conn = DBUtils.CreateDBConnection(ConnKey, out DataBaseType dbType))
                {
                    dataList = conn.Query<T>(sql, new { table = tblName, ids = idsin });
                }
            }
            return dataList;
        }

        /// <summary>
        /// 根据主键列表 获得实体对象集合
        /// </summary>
        /// <param name="ids">动态Id集合</param>
        /// <returns></returns>
        public IEnumerable<TReturn> GetList<TReturn>(IList<dynamic> ids) where TReturn : class
        {
            var tblName = string.Format("dbo.{0}", typeof(T).Name);
            var idsin = string.Join(",", ids.ToArray<dynamic>());
            var sql = "SELECT * FROM @table WHERE Id in (@ids)";
            DbConnObj ConnObj = GetConnObj();
            IEnumerable<TReturn> dataList = new List<TReturn>();
            if (ConnObj.DbConnection != null)
            {
                dataList = ConnObj.DbConnection.Query<TReturn>(sql, new { table = tblName, ids = idsin }, ConnObj.DbTransaction);
            }
            else
            {
                using (IDbConnection conn = DBUtils.CreateDBConnection(ConnKey, out DataBaseType dbType))
                {
                    dataList = conn.Query<TReturn>(sql, new { table = tblName, ids = idsin }, ConnObj.DbTransaction);
                }
            }
            return dataList;
        }

        /// <summary>
        /// 获取所有数据
        /// </summary>
        /// <returns></returns>
        public IEnumerable<T> GetList()
        {
            DbConnObj ConnObj = GetConnObj();
            if (ConnObj.DbConnection != null)
            {
                return ConnObj.DbConnection.GetList<T>(transaction: ConnObj.DbTransaction, dbType: ConnObj.DbType);
            }
            else
            {
                using (IDbConnection conn = DBUtils.CreateDBConnection(ConnKey, out DataBaseType dbType))
                {
                    return conn.GetList<T>(transaction: ConnObj.DbTransaction, dbType: dbType);
                }
            }
        }
        #endregion

        #region Get

        /// <summary>
        /// 根据条件筛选出数据集合
        /// </summary>
        /// <param name="sql">sql命令</param>
        /// <param name="param">动态参数</param>
        /// <param name="transaction">事务对象</param>
        /// <param name="commandTimeout">超时时间</param>
        /// <param name="commandType">命令类型</param>
        /// <returns></returns>
        public IEnumerable<T> Get(string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            DbConnObj ConnObj = GetConnObj(transaction);
            if (ConnObj.DbConnection != null)
            {
                return ConnObj.DbConnection.Query<T>(sql, param as object, ConnObj.DbTransaction, true, commandTimeout, commandType);
            }
            else
            {
                using (IDbConnection conn = DBUtils.CreateDBConnection(ConnKey, out DataBaseType dbType))
                {
                    return conn.Query<T>(sql, param as object, ConnObj.DbTransaction, true, commandTimeout, commandType);
                }
            }
        }

        /// <summary>
        /// 根据条件筛选出数据集合
        /// </summary>
        /// <typeparam name="TReturn">泛型约束</typeparam>
        /// <param name="sql">sql命令</param>
        /// <param name="param">动态参数</param>
        /// <param name="transaction">事务对象</param>
        /// <param name="commandTimeout">超时时间</param>
        /// <param name="commandType">命令类型</param>
        /// <returns></returns>
        public IEnumerable<TReturn> Get<TReturn>(string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null) where TReturn : class
        {
            DbConnObj ConnObj = GetConnObj(transaction);
            if (ConnObj.DbConnection != null)
            {
                return ConnObj.DbConnection.Query<TReturn>(sql, param as object, ConnObj.DbTransaction, true, commandTimeout, commandType);
            }
            else
            {
                using (IDbConnection conn = DBUtils.CreateDBConnection(ConnKey, out DataBaseType dbType))
                {
                    return conn.Query<TReturn>(sql, param as object, ConnObj.DbTransaction, true, commandTimeout, commandType);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <param name="commandType"></param>
        /// <returns></returns>
        public IEnumerable<TReturn> GetLastGrid<TReturn>(string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null) where TReturn : class
        {
            DbConnObj ConnObj = GetConnObj(transaction);
            IEnumerable<TReturn> result = null;
            if (ConnObj.DbConnection != null)
            {
                var query = ConnObj.DbConnection.QueryMultiple(sql, param as object, transaction, commandTimeout, commandType);
                while (!query.IsConsumed)
                {
                    result = query.Read<TReturn>();
                }
                return result;
            }
            else
            {
                using (IDbConnection conn = DBUtils.CreateDBConnection(ConnKey, out DataBaseType dbType))
                {
                    var query = conn.QueryMultiple(sql, param as object, transaction, commandTimeout, commandType);
                    while (!query.IsConsumed)
                    {
                        result = query.Read<TReturn>();
                    }
                    return result;
                }
            }
        }

        #endregion

        #region GetPage

        /// <summary>
        /// 分页
        /// </summary>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页大小</param>
        /// <param name="allRowsCount">条数</param>
        /// <param name="sql">sql命令</param>
        /// <param name="param">参数</param>
        /// <param name="allRowsCountSql">条数sql</param>
        /// <param name="allRowsCountParam">条数sql参数</param>
        /// <param name="commandTimeout">超时时间</param>
        /// <param name="commandType">命令类型</param>
        /// <returns></returns>
        public IEnumerable<T> GetPage(int pageIndex, int pageSize, out long allRowsCount, string sql, dynamic param = null, string allRowsCountSql = null, dynamic allRowsCountParam = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            DbConnObj ConnObj = GetConnObj();
            if (ConnObj.DbConnection != null)
            {
                return ConnObj.DbConnection.GetPage<T>(pageIndex, pageSize, out allRowsCount, sql, param as object, allRowsCountSql, ConnObj.DbTransaction, commandTimeout, ConnObj.DbType);
            }
            else
            {
                using (IDbConnection conn = DBUtils.CreateDBConnection(ConnKey, out DataBaseType dbType))
                {
                    return conn.GetPage<T>(pageIndex, pageSize, out allRowsCount, sql, param as object, allRowsCountSql, ConnObj.DbTransaction, commandTimeout, dbType);
                }
            }
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <typeparam name="TReturn">约束</typeparam>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页大小</param>
        /// <param name="allRowsCount">条数</param>
        /// <param name="sql">sql命令</param>
        /// <param name="param">参数</param>
        /// <param name="allRowsCountSql">条数sql</param>
        /// <param name="allRowsCountParam">条数sql参数</param>
        /// <param name="commandTimeout">超时时间</param>
        /// <param name="commandType">命令类型</param>
        /// <returns></returns>
        public IEnumerable<TReturn> GetPage<TReturn>(int pageIndex, int pageSize, out long allRowsCount, string sql, dynamic param = null, string allRowsCountSql = null, dynamic allRowsCountParam = null, int? commandTimeout = null, CommandType? commandType = null) where TReturn : class
        {
            DbConnObj ConnObj = GetConnObj();
            if (ConnObj.DbConnection != null)
            {
                return ConnObj.DbConnection.GetPage<TReturn>(pageIndex, pageSize, out allRowsCount, sql, param as object, allRowsCountSql, ConnObj.DbTransaction, commandTimeout, ConnObj.DbType);
            }
            else
            {
                using (IDbConnection conn = DBUtils.CreateDBConnection(ConnKey, out DataBaseType dbType))
                {
                    return conn.GetPage<TReturn>(pageIndex, pageSize, out allRowsCount, sql, param as object, allRowsCountSql, ConnObj.DbTransaction, commandTimeout, dbType);
                }
            }
        }

        #endregion

        #region LambdaUpdate

        /// <summary>
        /// LambdaUpdate
        /// </summary>
        /// <param name="transaction">事务对象</param>
        /// <param name="commandTimeout">超时时间</param>
        /// <returns></returns>
        public LambdaUpdateHelper<T> LambdaUpdate(IDbTransaction transaction = null, int? commandTimeout = null)
        {
            DbConnObj ConnObj = GetConnObj(transaction);
            if (ConnObj.DbConnection != null)
            {
                return ConnObj.DbConnection.LambdaUpdate<T>(transaction, commandTimeout);
            }
            else
            {
                return DapperExtension.LambdaUpdate<T>(ConnKey, commandTimeout);
            }
        }

        /// <summary>
        /// LambdaUpdate
        /// </summary>
        /// <typeparam name="TEntity">约束</typeparam>
        /// <param name="transaction">事务对象</param>
        /// <param name="commandTimeout">超时时间</param>
        /// <returns></returns>
        public LambdaUpdateHelper<TEntity> LambdaUpdate<TEntity>(IDbTransaction transaction = null, int? commandTimeout = null) where TEntity : class
        {
            DbConnObj ConnObj = GetConnObj(transaction);
            if (ConnObj.DbConnection != null)
            {
                return ConnObj.DbConnection.LambdaUpdate<TEntity>(transaction, commandTimeout);
            }
            else
            {
                return DapperExtension.LambdaUpdate<TEntity>(ConnKey, commandTimeout);
            }
        }

        #endregion

        #region LambdaQuery

        /// <summary>
        /// LambdaQuery
        /// </summary>
        /// <param name="transaction">事务对象</param>
        /// <param name="commandTimeout">超时时间</param>
        /// <returns></returns>
        public LambdaQueryHelper<T> LambdaQuery(IDbTransaction transaction = null, int? commandTimeout = null)
        {
            DbConnObj ConnObj = GetConnObj(transaction);
            if (ConnObj.DbConnection != null)
            {
                return ConnObj.DbConnection.LambdaQuery<T>(transaction, commandTimeout);
            }
            else
            {
                return DapperExtension.LambdaQuery<T>(ConnKey, commandTimeout);
            }
        }

        /// <summary>
        /// LambdaQuery
        /// </summary>
        /// <typeparam name="TEntity">约束</typeparam>
        /// <param name="transaction">事务对象</param>
        /// <param name="commandTimeout">超时时间</param>
        /// <returns></returns>
        public LambdaQueryHelper<TEntity> LambdaQuery<TEntity>(IDbTransaction transaction = null, int? commandTimeout = null) where TEntity : class
        {
            DbConnObj ConnObj = GetConnObj(transaction);
            if (ConnObj.DbConnection != null)
            {
                return ConnObj.DbConnection.LambdaQuery<TEntity>(transaction, commandTimeout);
            }
            else
            {
                return DapperExtension.LambdaQuery<TEntity>(ConnKey, commandTimeout);
            }
        }

        #endregion

        #region 创建数据库连接对象
        /// <summary>
        /// 创建数据库连接对象
        /// </summary>
        /// <param name="transaction">事务</param>
        /// <returns></returns>
        public DbConnObj GetConnObj(IDbTransaction transaction = null)
        {
            DbConnObj dbConnObj = new DbConnObj();
            if (null != transaction)
            {
                dbConnObj.DbConnection = transaction.Connection;
                dbConnObj.DbTransaction = transaction;
            }
            else if (null != DBSession)
            {
                if (DBSession.Connection.ConnectionString == "")
                {
                    DBSession = Helper.GetPerHttpRequestDBSession(ConnKey);
                }
                dbConnObj.DbConnection = this.DBSession.Connection;
                dbConnObj.DbType = this.DBSession.DbType;
            }
            return dbConnObj;
        }

        #endregion
    }
}