首页 > 代码库 > C# 调用配置文件SQL语句 真2B!

C# 调用配置文件SQL语句 真2B!

/*********************************************************************************
** File Name    :    SQLConfig
** Copyright (C) 2013 guzhen.net. All Rights Reserved.
** Creator        :    SONGGUO\wangxiaoming
** Create Date    :    2013/1/23 10:47:36
** Update Date    :    
** Description    :    
** Version No    :    
*********************************************************************************/
using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
using System.Reflection;
using System.Configuration;
using System.Runtime.Caching;
using System.IO;

namespace System.Data
{
    /// <summary>
    /// 配置映射
    /// </summary>
    internal class SQLConfig
    {
        private ObjectCache _cache;
        private string _configPath;

        /// <summary>
        /// Constractor
        /// </summary>
        /// <param name="configPath">配置文件的路径</param>
        public SQLConfig(string configPath = null)
        {
            if (configPath == null)
            {
                configPath = AppDomain.CurrentDomain.BaseDirectory + @"\DbSetting\";
            }

            _cache = new MemoryCache(this.GetType().FullName);
            _configPath = configPath;
        }

        private void GenerateKey(MethodBase method, out string key)
        {
            key = method.DeclaringType.Name + "." + method.Name;
        }

        private bool TryFindText(string key, out string text, out string configPath)
        {
            configPath = text = null;
            foreach (string filePath in Directory.EnumerateFiles(_configPath, "*.config"))
            {
                var map = new ExeConfigurationFileMap();
                map.ExeConfigFilename = filePath;
                var config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
                var pair = config.AppSettings.Settings[key];
                if (pair != null)
                {
                    text = pair.Value;
                    configPath = filePath;
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 获取调用的方法映射的SQL语句
        /// </summary>
        /// <param name="method">调用的方法</param>
        /// <returns>SQL语句</returns>
        /// <exception cref="Guzhen.Common.DbLiteException"></exception>
        public string GetSQL(MethodBase method)
        {
            string key;
            this.GenerateKey(method, out key);
            string sql = (string)_cache[key], configPath;
            if (sql == null)
            {
                if (!this.TryFindText(key, out sql, out configPath))
                {
                    throw new InvalidOperationException(string.Format("没有配置{0}该项", key));
                }
                var policy = new CacheItemPolicy()
                {
                    AbsoluteExpiration = ObjectCache.InfiniteAbsoluteExpiration,
                    //相对过期时间
                    SlidingExpiration = TimeSpan.FromMinutes(10D),
                };
                //监控配置文件变更
                try
                {
                    policy.ChangeMonitors.Add(new HostFileChangeMonitor(new List<string>() { configPath }));
                }
                catch (Exception ex)
                {
                    App.LogError(ex, string.Format("ChangeMonitor:{0}", ex.Message));
                }
                _cache.Add(key, sql, policy);
            }
            return sql;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.Common;
using System.Reflection;
using System.Diagnostics;
using System.Runtime.Caching;
using System.Runtime.CompilerServices;

namespace System.Data
{
    /// <summary>
    /// MultipleActiveResultSets=True;
    /// </summary>
    public class Database : IRequiresFactory
    {
        #region Static
        internal const string ReturnParameterName = "@RETURN_VALUE";
        internal const string DataTableName = "T";
        private static SQLConfig Config;

        static Database()
        {
            Config = new SQLConfig();
        }
        #endregion

        #region Fields
        private DbFactory _factory;
        protected readonly ObjectCache Cache;
        #endregion

        #region Properties
        public virtual DbFactory Factory
        {
            get { return _factory; }
        }
        public bool SupportStoredProc
        {
            get { return Cache != null; }
        }
        #endregion

        #region Constructors
        public Database(DbFactory factory, int? spCacheMemoryLimitMegabytes = null)
        {
            _factory = factory;
            if (spCacheMemoryLimitMegabytes != null)
            {
                Cache = new MemoryCache(string.Format("Database[{0}]", factory.Name), new System.Collections.Specialized.NameValueCollection() { { "cacheMemoryLimitMegabytes", spCacheMemoryLimitMegabytes.Value.ToString() } });
            }
        }
        #endregion

        #region NativeMethods
        public DbCommand PrepareCommand(string text, CommandType type)
        {
            DbCommand cmd;
            var scope = DbScope.Current;
            if (scope != null)
            {
                cmd = scope.PrepareCommand(this);
                cmd.CommandText = text;
            }
            else
            {
                cmd = _factory.CreateCommand(text);
            }
            cmd.CommandType = type;
            return cmd;
        }

        protected int ExecuteNonQuery(DbCommand cmd)
        {
            if (cmd.Connection == null)
            {
                cmd.Connection = _factory.CreateConnection();
            }
            bool isClosed = cmd.Connection.State == ConnectionState.Closed;
            try
            {
                if (isClosed)
                {
                    cmd.Connection.Open();
                }
                return cmd.ExecuteNonQuery();
            }
            finally
            {
                if (isClosed)
                {
                    cmd.Connection.Close();
                }
            }
        }

        protected object ExecuteScalar(DbCommand cmd)
        {
            if (cmd.Connection == null)
            {
                cmd.Connection = _factory.CreateConnection();
            }
            bool isClosed = cmd.Connection.State == ConnectionState.Closed;
            try
            {
                if (isClosed)
                {
                    cmd.Connection.Open();
                }
                return cmd.ExecuteScalar();
            }
            finally
            {
                if (isClosed)
                {
                    cmd.Connection.Close();
                }
            }
        }

        protected DbDataReader ExecuteReader(DbCommand cmd)
        {
            if (cmd.Connection == null)
            {
                cmd.Connection = _factory.CreateConnection();
            }
            bool isClosed = cmd.Connection.State == ConnectionState.Closed;
            if (isClosed)
            {
                cmd.Connection.Open();
            }
            return cmd.ExecuteReader(isClosed ? CommandBehavior.CloseConnection : CommandBehavior.Default);
        }

        protected DataTable ExecuteDataTable(DbCommand cmd, int startRecord = -1, int maxRecords = 0)
        {
            var dt = new DataTable(DataTableName);
            if (cmd.Connection == null)
            {
                cmd.Connection = _factory.CreateConnection();
            }
            using (DbDataAdapter da = _factory.CreateDataAdapter(cmd))
            {
                if (startRecord == -1)
                {
                    da.Fill(dt);
                }
                else
                {
                    da.Fill(startRecord, maxRecords, dt);
                }
            }
            return dt;
        }

        protected DataSet ExecuteDataSet(DbCommand cmd)
        {
            var ds = new DataSet();
            if (cmd.Connection == null)
            {
                cmd.Connection = _factory.CreateConnection();
            }
            using (DbDataAdapter da = _factory.CreateDataAdapter(cmd))
            {
                da.Fill(ds, DataTableName);
            }
            return ds;
        }
        #endregion

        #region Methods
        /// <summary>
        /// 使用调用方法最为映射方法来获取DataReader
        /// </summary>
        /// <param name="db"></param>
        /// <param name="paramValues">按SQL语句中定义的Format顺序,对应传递参数值</param>
        /// <returns>DataReader</returns>
        [MethodImpl(MethodImplOptions.NoInlining)]
        public int MappedExecNonQuery(params object[] paramValues)
        {
            var stack = new StackTrace();
            MethodBase method = stack.GetFrame(1).GetMethod();
            string sql = Config.GetSQL(method);
            return this.ExecuteNonQuery(sql, paramValues);
        }
        public int ExecuteNonQuery(string formatSql, params object[] paramValues)
        {
            string text = DbUtility.GetFormat(formatSql, paramValues);
            var cmd = this.PrepareCommand(text, CommandType.Text);
            return this.ExecuteNonQuery(cmd);
        }

        /// <summary>
        /// 使用调用方法最为映射方法来获取DataReader
        /// </summary>
        /// <param name="db"></param>
        /// <param name="paramValues">按SQL语句中定义的Format顺序,对应传递参数值</param>
        /// <returns>DataReader</returns>
        [MethodImpl(MethodImplOptions.NoInlining)]
        public T ExecuteScalar<T>(params object[] paramValues)
        {
            var stack = new StackTrace();
            MethodBase method = stack.GetFrame(1).GetMethod();
            string sql = Config.GetSQL(method);
            return this.ExecuteScalar<T>(sql, paramValues);
        }
        public T ExecuteScalar<T>(string formatSql, params object[] paramValues)
        {
            string text = DbUtility.GetFormat(formatSql, paramValues);
            var cmd = this.PrepareCommand(text, CommandType.Text);
            return (T)Convert.ChangeType(this.ExecuteScalar(cmd), typeof(T));
        }

        /// <summary>
        /// 使用调用方法最为映射方法来获取DataReader
        /// </summary>
        /// <param name="db"></param>
        /// <param name="paramValues">按SQL语句中定义的Format顺序,对应传递参数值</param>
        /// <returns>DataReader</returns>
        [MethodImpl(MethodImplOptions.NoInlining)]
        public DbDataReader MappedExecReader(params object[] paramValues)
        {
            var stack = new StackTrace();
            MethodBase method = stack.GetFrame(1).GetMethod();
            string sql = Config.GetSQL(method);
            return this.ExecuteReader(sql, paramValues);
        }
        public DbDataReader ExecuteReader(string formatSql, params object[] paramValues)
        {
            string text = DbUtility.GetFormat(formatSql, paramValues);
            var cmd = this.PrepareCommand(text, CommandType.Text);
            return this.ExecuteReader(cmd);
        }

        public DataTable ExecuteDataTable(string formatSql, params object[] paramValues)
        {
            return this.ExecuteDataTable(-1, 0, formatSql, paramValues);
        }
        public DataTable ExecuteDataTable(int startRecord, int maxRecords, string formatSql, params object[] paramValues)
        {
            string text = DbUtility.GetFormat(formatSql, paramValues);
            var cmd = this.PrepareCommand(text, CommandType.Text);
            return this.ExecuteDataTable(cmd, startRecord, maxRecords);
        }

        public int UpdateDataTable(DataTable dt, params string[] joinSelectSql)
        {
            int affected = 0;
            var cmd = this.PrepareCommand(string.Empty, CommandType.Text);
            using (var da = this.Factory.CreateDataAdapter(cmd))
            using (var cb = this.Factory.CreateCommandBuilder(da))
            {
                da.AcceptChangesDuringUpdate = false;
                affected = da.Update(dt);
                if (!joinSelectSql.IsNullOrEmpty())
                {
                    for (int i = 0; i < joinSelectSql.Length; i++)
                    {
                        cb.RefreshSchema();
                        da.SelectCommand.CommandText = joinSelectSql[i];
                        affected += da.Update(dt);
                    }
                }
                dt.AcceptChanges();
            }
            return affected;
        }
        #endregion

        #region StoredProc
        #region Command
        /// <summary>
        /// cmd.CommandType = CommandType.StoredProcedure;
        /// Always discoveredParameters[0].ParameterName == Database.ReturnParameterName
        /// </summary>
        /// <param name="cmd"></param>
        /// <returns></returns>
        protected DbParameter[] GetDeriveParameters(DbCommand cmd)
        {
            string spName = cmd.CommandText;
            DbParameter[] discoveredParameters = (DbParameter[])Cache[spName];
            if (discoveredParameters == null)
            {
                string qualifiedName = cmd.GetType().AssemblyQualifiedName;
                Type builderType = Type.GetType(qualifiedName.Insert(qualifiedName.IndexOf(,), "Builder"));
                MethodInfo method = builderType.GetMethod("DeriveParameters", BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod);
                if (method == null)
                {
                    throw new ArgumentException("The specified provider factory doesn‘t support stored procedures.");
                }
                if (cmd.Connection == null)
                {
                    cmd.Connection = _factory.CreateConnection();
                }
                bool isClosed = cmd.Connection.State == ConnectionState.Closed;
                try
                {
                    if (isClosed)
                    {
                        cmd.Connection.Open();
                    }
                    method.Invoke(null, new object[] { cmd });
                }
                finally
                {
                    if (isClosed)
                    {
                        cmd.Connection.Close();
                    }
                }
                Cache[spName] = discoveredParameters = new DbParameter[cmd.Parameters.Count];
                cmd.Parameters.CopyTo(discoveredParameters, 0);
                cmd.Parameters.Clear();
            }
            return discoveredParameters;
        }

        public void DeriveParameters(DbCommand cmd)
        {
            DbParameter[] originalParameters = GetDeriveParameters(cmd);
            for (int i = 0; i < originalParameters.Length; i++)
            {
                cmd.Parameters.Add(((ICloneable)originalParameters[i]).Clone());
            }
        }

        public void DeriveAssignParameters(DbCommand cmd, object[] values)
        {
            DbParameter[] discoveredParameters = GetDeriveParameters(cmd);
            if (cmd.Parameters.Count > 0 || discoveredParameters.Length - 1 != values.Length)
            {
                throw new ArgumentException("The number of parameters doesn‘t match number of values for stored procedures.");
            }
            cmd.Parameters.Add(((ICloneable)discoveredParameters[0]).Clone());
            for (int i = 0; i < values.Length; )
            {
                object value = http://www.mamicode.com/values[i] ?? DBNull.Value;
                DbParameter discoveredParameter = discoveredParameters[++i];
                object cloned = ((ICloneable)discoveredParameter).Clone();
                ((DbParameter)cloned).Value = value;
                cmd.Parameters.Add(cloned);
            }
        }

        public void SetParameterValue(DbCommand cmd, int index, object value)
        {
            int startIndex = cmd.Parameters.Count > 0 && cmd.Parameters[0].ParameterName == ReturnParameterName ? 1 : 0;
            cmd.Parameters[startIndex + index].Value =http://www.mamicode.com/ value;
        }
        public void SetParameterValue(DbCommand cmd, string name, object value)
        {
            cmd.Parameters[_factory.ParameterNamePrefix + name].Value =http://www.mamicode.com/ value;
        }

        public object GetParameterValue(DbCommand cmd, int index)
        {
            int startIndex = cmd.Parameters.Count > 0 && cmd.Parameters[0].ParameterName == ReturnParameterName ? 1 : 0;
            return cmd.Parameters[startIndex + index].Value;
        }
        public object GetParameterValue(DbCommand cmd, string name)
        {
            return cmd.Parameters[_factory.ParameterNamePrefix + name].Value;
        }

        public object GetParameterReturnValue(DbCommand cmd)
        {
            if (cmd.Parameters.Count > 0 && cmd.Parameters[0].ParameterName == ReturnParameterName)
            {
                return cmd.Parameters[0].Value;
            }
            return null;
        }
        #endregion

        #region Execute
        protected virtual void FillOutputValue(DbCommand cmd, object[] values)
        {
            for (int i = 1; i < cmd.Parameters.Count; i++)
            {
                var param = cmd.Parameters[i];
                if (param.Direction == ParameterDirection.Output || param.Direction == ParameterDirection.InputOutput)
                {
                    values[i - 1] = param.Value;
                }
            }
        }

        public int ExecuteStoredProcNonQuery(string spName, params object[] values)
        {
            var cmd = this.PrepareCommand(spName, CommandType.StoredProcedure);
            DeriveAssignParameters(cmd, values);
            FillOutputValue(cmd, values);
            return ExecuteNonQuery(cmd);
        }

        public object ExecuteStoredProcScalar(string spName, params object[] values)
        {
            var cmd = this.PrepareCommand(spName, CommandType.StoredProcedure);
            DeriveAssignParameters(cmd, values);
            FillOutputValue(cmd, values);
            return ExecuteScalar(cmd);
        }

        public DbDataReader ExecuteStoredProcReader(string spName, params object[] values)
        {
            var cmd = this.PrepareCommand(spName, CommandType.StoredProcedure);
            DeriveAssignParameters(cmd, values);
            FillOutputValue(cmd, values);
            return ExecuteReader(cmd);
        }

        public DataTable ExecuteStoredProcDataTable(string spName, params object[] values)
        {
            var cmd = this.PrepareCommand(spName, CommandType.StoredProcedure);
            DeriveAssignParameters(cmd, values);
            FillOutputValue(cmd, values);
            return ExecuteDataTable(cmd);
        }

        public DataSet ExecuteStoredProcDataSet(string spName, params object[] values)
        {
            var cmd = this.PrepareCommand(spName, CommandType.StoredProcedure);
            DeriveAssignParameters(cmd, values);
            FillOutputValue(cmd, values);
            return ExecuteDataSet(cmd);
        }
        #endregion
        #endregion
    }
}