项目需要,需要一个通用的数据库操作类,增删改查、事务、存储过程、日志记录都要有,于是在已有的帮助类上做了一些改进,并将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);
一次搞定,以后的项目基本都可以复用,还是值得花些时间来整理理解的,每次都重新编码或是搜集别人的代码怎么说效率都比较低下,没必要!