項目需要,需要一個通用的數據庫操作類,增刪改查、事務、存儲過程、日志記錄都要有,於是在已有的幫助類上做了一些改進,並將log4j的.NET版--log4net嵌入其中記錄sql的執行環境和狀態。
用起來還是比較順手的,因此分享一下供參考。其中log4net需要通過VS的NuGet程序包管理器引入然后引用。
日志記錄功能只是個輔助,先說一下數據庫幫助類的主體思路:
成員變量:
- 數據庫連接字符串
- 數據庫連接(根據字符串實例化得到的SqlConnection對象)
- 事務
- 參數鍵值對
- 用於記錄日志的實例
構造方法:(供外部初始化調用)
- 無參(默認的連接字符串)
- 有參(指定連接字符串)
輔助功能方法:(主要供內部調用)
- 打開、關閉、釋放數據庫連接(使用比較頻繁)
- 參數初始化、清空(多個地方用到)
- Command生成與設置(每次sql執行必不可少的操作)
- GetDataAdapter等中間結果函數(若是返回DataSet,DataTable結果集都會用到)
供外部調用方法:
- 添加參數
- 返回執行成敗的結果
- 返回數據集(DataSet,DataTable,DataReader)
- 執行存儲過程、事務
1. LogHelper:
1 using log4net; 2 using log4net.Layout; 3 using System.Collections.Generic; 4 5 namespace CH_Common 6 { 7 public class LogHelper 8 { 9 private static ILog log; 10 private static LogHelper logHelper; 11 public static ILog GetInstance() 12 { 13 logHelper = new LogHelper(); 14 return log; 15 } 16 public static ILog GetInstance(string configPath) 17 { 18 logHelper = new LogHelper(configPath); 19 return log; 20 } 21 private LogHelper() 22 { 23 log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 24 } 25 26 private LogHelper(string configPath) 27 { 28 log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo(configPath)); 29 log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 30 } 31 32 } 33 }
2. DBHelper:
using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Linq; using System.Text; using System.Threading.Tasks; using log4net; using System.Configuration; namespace CH_Common { public class DBHelper { #region 成員變量 string connectionString; SqlConnection connection; SqlTransaction transaction; Hashtable listParameters; private ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); #endregion #region 構造方法 /// <summary> /// 默認構造方法 /// </summary> public DBHelper() { this.connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
connection = new SqlConnection(connectionString); } /// <summary> /// 含參的構造方法 /// </summary> /// <param name="connectionString">連接字符串</param> public DBHelper(string connectionString) { this.connectionString = connectionString; connection = new SqlConnection(connectionString); } #endregion #region 數據庫連接的打開、關閉、釋放 /// <summary> /// 打開數據庫連接 /// </summary> public void Open() { if (connection.State == ConnectionState.Closed) { connection.Open(); } } /// <summary> /// 關閉數據庫連接 /// </summary> public void Close() { if (connection.State.ToString() == "Open") { connection.Close(); InitMember(); } } /// <summary> /// 參數初始化 /// </summary> void InitMember() { listParameters = null; //cmd = null; } /// <summary> /// 釋放連接 /// </summary> public void Dispose() { if (connection != null) { connection.Close(); connection.Dispose(); } GC.Collect(); } #endregion #region 設置連接字符串 /// <summary> /// 設置連接字符串 /// </summary> /// <param name="strConnectionString">連接字符串</param> public void SetConnection(string strConnectionString) { connectionString = strConnectionString; connection = new SqlConnection(connectionString); } #endregion #region Command的生成與設置 /// <summary> /// 設置Command /// </summary> /// <param name="SQL">SQL文</param> /// <param name="cmdType">CommandType</param> private SqlCommand SetCmd(string SQL, CommandType cmdType) { Open(); SqlCommand cmd = new SqlCommand(SQL, connection); if (null != transaction) { cmd.Transaction = transaction; } cmd.CommandType = cmdType; cmd.CommandText = SQL; cmd.Parameters.Clear(); string strSQLLog = ""; if (listParameters != null) { foreach (DictionaryEntry parameter in listParameters) { cmd.Parameters.Add(new SqlParameter(parameter.Key.ToString(), parameter.Value)); strSQLLog = strSQLLog + "[" + parameter.Key.ToString() + "]=[" + parameter.Value.ToString() + "]"; } log.Info(strSQLLog); ClearParameter(); } return cmd; } /// <summary> /// 生成Commond /// </summary> /// <param name="SQL"></param> /// <returns></returns> private SqlCommand CreateCmd(string SQL) { return SetCmd(SQL, CommandType.Text); } private SqlCommand CreateProc(string procName) { return SetCmd(procName, CommandType.StoredProcedure); } #endregion #region SqlDataReader返回 /// <summary> /// SqlDataReader返回 /// </summary> /// <param name="SQL">SQL文</param> /// <returns>SqlDataReader</returns> private SqlDataReader ReturnDataReader(string SQL) { return CreateCmd(SQL).ExecuteReader(); } #endregion #region SqlParameter參數追加 /// <summary> /// SqlParameter參數追加 /// </summary> /// <param name="ParamName">參數名</param> /// <param name="Value">參數值</param> public void AddParameter(string ParamName, object Value) { try { if (listParameters == null) { listParameters = new Hashtable(); } listParameters.Add(ParamName, Value); } catch (Exception ex) { log.Error("Add SqlParameter Error: " + ex.Message); log.Error(ex); throw ex; } } #endregion #region SqlParameter清空 /// <summary> /// SqlParameter清空 /// </summary> public void ClearParameter() { listParameters = null; } #endregion #region SqlDataAdapter適配器返回 /// <summary> /// SqlDataAdapter適配器返回 /// </summary> /// <param name="SQL">SQL語句</param> /// <returns>SqlDataAdapter對象</returns> private SqlDataAdapter GetDataAdapter(string SQL) { SqlDataAdapter Da = new SqlDataAdapter(); Da.SelectCommand = SetCmd(SQL, CommandType.Text); SqlCommandBuilder custCB = new SqlCommandBuilder(Da); return Da; } #endregion #region SQL執行 /// <summary> /// SQL執行 /// </summary> /// <param name="SQL">SQL語句</param> /// <returns>-1:失敗 其他:成功</returns> public int ExeCmd(string SQL) { int ret = -1; string strSQLLog = string.Empty; string sqlLog = ""; if (listParameters != null) { strSQLLog = SQL; foreach (DictionaryEntry parameter in listParameters) { strSQLLog = strSQLLog.Replace("@" + parameter.Key.ToString(), "'" + parameter.Value.ToString() + "'"); sqlLog = sqlLog + "[" + parameter.Key.ToString() + "]=[" + parameter.Value.ToString() + "]"; } } try { log.Info("SQL Execute Start:" + SQL + " " + sqlLog); ret = CreateCmd(SQL).ExecuteNonQuery(); log.Info("SQL Execute End"); } catch (Exception ex) { log.Error("SQL Execute Error Occured:" + SQL + " " + sqlLog); log.Error("SQL Execute ErrorMessage:" + ex.Message); log.Error(ex); RollbackTransaction(); throw ex; } finally { if (null == transaction) { Close(); } ClearParameter(); } return ret; } #endregion #region DataSet返回 /// <summary> /// SQL執行 /// </summary> /// <param name="SQL">SQL文</param> /// <returns>DataSet</returns> public DataSet ReturnDataSet(string SQL) { DataSet Ds = new DataSet(); try { log.Info("SQL Execute Start:" + SQL); SqlDataAdapter Da = GetDataAdapter(SQL); Da.Fill(Ds); log.Info("SQL Execute End"); } catch (Exception ex) { log.Error("SQL Execute Error Occured:" + SQL); log.Error("SQL Execute ErrorMessage:" + ex.Message); log.Error(ex); throw ex; } finally { if (null == transaction) { Close(); } } return Ds; } #endregion #region DataTable返回 /// <summary> /// DataTable返回 /// </summary> /// <param name="SQL">SQL文</param> /// <returns>DataTable</returns> public DataTable ReturnDataTable(string SQL) { DataTable dt = new DataTable("tempDt");//跨進程序列化,需要為datatable命名 try { log.Info("SQL Execute Start:" + SQL); SqlDataAdapter Da = GetDataAdapter(SQL); Da.Fill(dt); log.Info("SQL Execute End"); } catch (Exception ex) { log.Error("SQL Execute Error Occured:" + SQL); log.Error("SQL Execute ErrorMessage:" + ex.Message); log.Error(ex); throw ex; } finally { if (null == transaction) { Close(); } } return dt; } #endregion #region 事務 /// <summary> /// 開始事務 /// </summary> public void BeginTransaction() { Open(); //cmd = connection.CreateCommand(); transaction = connection.BeginTransaction(); //cmd.Transaction = transaction; } /// <summary> /// 提交事務 /// </summary> public void CommitTransaction() { try { if (null != transaction) { transaction.Commit(); } } catch (System.Exception ex) { log.Error("transaction error:" + ex.Message); log.Error(ex); transaction.Rollback(); throw ex; } finally { transaction = null; Close(); } } /// <summary> /// 回滾事務 /// </summary> public void RollbackTransaction() { if (null != transaction) { transaction.Rollback(); transaction = null; } } #endregion #region 存儲過程 /// <summary> /// 執行存儲過程 /// </summary> /// <param name="proc_name"></param> /// <returns></returns> public int ExecProcedure(string proc_name) { int ret = -1; string strSQLLog = string.Empty; string sqlLog = ""; if (listParameters != null) { foreach (DictionaryEntry parameter in listParameters) { strSQLLog = strSQLLog.Replace("@" + parameter.Key.ToString(), "'" + parameter.Value.ToString() + "'"); sqlLog = sqlLog + "[" + parameter.Key.ToString() + "]=[" + parameter.Value.ToString() + "]"; } } try { log.Info("Procedure Execute Start:" + proc_name + " " + sqlLog); ret = CreateProc(proc_name).ExecuteNonQuery(); log.Info("Procedure Execute End"); } catch (Exception ex) { log.Error("Procedure Execute Error Occured:" + proc_name + " " + sqlLog); log.Error("Procedure Execute ErrorMessage:" + ex.Message); log.Error(ex); RollbackTransaction(); throw ex; } finally { if (null == transaction) { Close(); } ClearParameter(); } return ret; } #endregion } }
3. log4net配置文件:
<configuration> <configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/> </configSections> <log4net> <!-- 日志輸出定義 --> <appender name="ReceiveLogFileAppender" type="log4net.Appender.RollingFileAppender"> <param name="file" type="log4net.Util.PatternString" value="Logs" /> <param name="LockingModel" type="log4net.Appender.FileAppender+MinimalLock" /> <param name="StaticLogFileName" value="false" /> <!--混合(大小與日期)--> <param name="rollingStyle" value="Composite" /> <param name="DatePattern" value="/yyyyMMdd/'info.'yyyyMMdd'.log'" /> <!--單個日志文件大小上限5M--> <param name="maximumFileSize" value="5MB" /> <!--1.2.3計數類型--> <param name="CountDirection" value="1"/> <!--最多產生的日志文件數,超過則只保留最新的(n+1)個。設定值value="-1"為不限文件數--> <param name="MaxSizeRollBackups" value="-1" /> <!--追加--> <param name="AppendToFile" value="true" /> <!-- 日志格式 --> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="%d{yyyy/MM/dd_HH:mm:ss.fff} %t %-8p %C %M %m %exception%n" /> </layout> <!-- 應用此配置的過濾器 --> <filter type="log4net.Filter.LevelRangeFilter"> <levelMin value="DEBUG" /> <levelMax value="INFO" /> </filter> </appender> <appender name="ErrorLogFileAppender" type="log4net.Appender.RollingFileAppender"> <param name="file" type="log4net.Util.PatternString" value="Logs" /> <param name="LockingModel" type="log4net.Appender.FileAppender+MinimalLock" /> <param name="StaticLogFileName" value="false" /> <!--混合(大小與日期)--> <param name="rollingStyle" value="Composite" /> <param name="DatePattern" value="/yyyyMMdd/'error.'yyyyMMdd'.log'" /> <!--單個日志文件大小上限5M--> <param name="maximumFileSize" value="5MB" /> <!--1.2.3計數類型--> <param name="CountDirection" value="1"/> <!--最多產生的日志文件數,超過則只保留最新的n個。設定值value="-1"為不限文件數--> <param name="MaxSizeRollBackups" value="-1" /> <!--追加--> <param name="AppendToFile" value="true" /> <!-- 日志格式 --> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="%d{yyyy/MM/dd_HH:mm:ss.fff} %t %-8p %C %M %m %exception%n" /> </layout> <!-- 應用此配置的過濾器----> <filter type="log4net.Filter.LevelRangeFilter"> <levelMin value="ERROR" /> <levelMax value="FATAL" /> </filter> </appender> <root> <level value="INFO" /> <appender-ref ref="ReceiveLogFileAppender" /> <appender-ref ref="ErrorLogFileAppender" /> </root> </log4net> </configuration>
幫助類的用法非常簡便:
1.new 一個DBHelper對象dbhelper出來;
2.sql文中需要傳入參數時:dbhelper.AddParameter(“@para”,“para”);
3.執行sql返回結果:dbhelper.ReturnDataTable(sql);
一次搞定,以后的項目基本都可以復用,還是值得花些時間來整理理解的,每次都重新編碼或是搜集別人的代碼怎么說效率都比較低下,沒必要!