平時使用的數據庫操作類整理更新后備份,記錄下來以供以后使用,並順便分享給大家一起交流。直接上源碼:
整個底層操作方法分為4個類,基礎方法類:SqlBase 基礎工具類:SqlTool 日志類:DbLog 和MSSQL操作類:MsSqlHelper。
由於平時工作未用到其他類型數據庫,因此未整理其他數據庫的操作類,以后用到的話會進行更新。
首先是通用的數據庫底層操作方法整理:
/// <summary> /// 數據庫操作基礎方法類 /// </summary> public class SqlBase { #region 字段與屬性聲明 private static int _cmdTimeOut = 30; /// <summary> /// 等待命令執行的時間(以秒為單位) /// </summary> public static int CMDTimeOut { get { return _cmdTimeOut; } set { _cmdTimeOut = value; } } private static string _defaultDb = "conn"; /// <summary> /// 默認數據庫連接配置名稱 /// </summary> public static string DefaultDb { get { return _defaultDb; } set { _defaultDb = value; } } /// <summary> /// 默認數據集名稱 /// </summary> private static string _defaultDataSet = "ds"; /// <summary> /// 默認數據表名稱 /// </summary> private static string _defaultDataTable = "dt"; /// <summary> /// 數據庫連接失敗返回信息 /// </summary> private static string _linkErrMsg = "數據庫連接失敗"; /// <summary> /// 存儲過程返回值參數名 /// </summary> private static string _returnParaName = "ReturnValue"; #endregion /// <summary> /// 默認數據庫連接字符串 /// </summary> public static string _connStr = String.Empty; /// <summary> /// 獲取數據庫連接 /// </summary> /// <param name="useDb">數據庫簡寫</param> public static string GetConnectionString(string useDb) { switch (useDb) { case "conn": return _connStr; default: useDb = DefaultDb; break; } return System.Configuration.ConfigurationManager.AppSettings[useDb].ToString(); } /// <summary> /// 獲取數據庫連接 /// </summary> /// <param name="useDb">數據庫簡寫</param> private static SqlConnection GetConnection(string useDb) { if (String.IsNullOrEmpty(useDb)) useDb = DefaultDb; var connStr = GetConnectionString(useDb); if (!String.IsNullOrEmpty(connStr)) { return new SqlConnection(connStr); } return null; } /// <summary> /// 執行數據庫操作 /// </summary> /// <param name="sql">數據庫執行語句</param> /// <param name="useDb">數據庫簡寫</param> /// <returns>受到影響的行數</returns> public static int ExecuteNonQuery(string sql, string useDb = "") { return ExecuteNonQuery(sql, null, useDb); } /// <summary> /// 執行數據庫操作 /// </summary> /// <param name="sql">數據庫執行語句</param> /// <param name="paras">參數集</param> /// <param name="useDb">數據庫簡寫</param> /// <returns>受影響的行數</returns> public static int ExecuteNonQuery(string sql, SqlParameter[] paras, string useDb = "") { SqlConnection conn = GetConnection(useDb); try { if (conn == null) throw new Exception(_linkErrMsg); conn.Open(); var cmd = new SqlCommand(sql, conn); cmd.CommandTimeout = CMDTimeOut; cmd.Parameters.Clear(); if (paras != null) { cmd.Parameters.AddRange(paras); } return cmd.ExecuteNonQuery(); } catch (System.Data.SqlClient.SqlException e) { throw e; } finally { if (conn != null) conn.Close(); } } /// <summary> /// 執行SQL語句並返回受影響的行數,帶事務操作 /// </summary> /// <param name="trans">事務</param> /// <param name="sql">數據庫執行語句</param> /// <param name="paras">參數集</param> /// <returns></returns> public static int ExecuteNonQuery(SqlTransaction trans, string sql, SqlParameter[] paras = null) { try { if (trans.Connection.State == ConnectionState.Closed) { trans.Connection.Open(); } SqlCommand command = new SqlCommand(sql, trans.Connection); command.CommandTimeout = CMDTimeOut; command.Transaction = trans; command.Parameters.Clear(); if (paras != null) { command.Parameters.AddRange(paras); } return command.ExecuteNonQuery(); } catch (Exception e) { throw e; } finally { trans.Connection.Close(); } } /// <summary> /// 執行SQL語句並返回受影響的行數,帶事務操作(只針對sqlserver) /// </summary> /// <param name="sql"></param> /// <param name="paras"></param> /// <returns></returns> public static int ExecuteNonQueryWithTransation(string sql, SqlParameter[] paras = null, string useDB = "") { SqlTransaction sqlTransaction = null; SqlConnection conn = GetConnection(useDB); try { if (conn == null) throw new Exception(_linkErrMsg); conn.Open(); sqlTransaction = conn.BeginTransaction(); var cmd = new SqlCommand(sql, conn); cmd.CommandTimeout = CMDTimeOut; cmd.Transaction = sqlTransaction; cmd.Parameters.Clear(); if (paras != null) { cmd.Parameters.AddRange(paras); } var ret = cmd.ExecuteNonQuery(); sqlTransaction.Commit(); return ret; } catch (System.Data.SqlClient.SqlException e) { sqlTransaction.Rollback(); throw e; } finally { if (conn != null) conn.Close(); } } /// <summary> /// 執行查詢,並返回查詢所返回的結果集中第一行的第一列。忽略其他列或行。 /// </summary> /// <param name="sql">數據庫執行語句</param> /// <param name="parameters">參數集</param> /// <param name="useDb">數據庫簡寫</param> /// <returns>返回查詢所返回的結果集中第一行的第一列或空引用(如果結果集為空).忽略其他列或行</returns> public static object ExecuteScalar(string sql, string useDb = "") { return ExecuteScalar(sql, null, useDb); } /// <summary> /// 執行查詢,並返回查詢所返回的結果集中第一行的第一列。忽略其他列或行。 /// </summary> /// <param name="sql">計算查詢結果語句</param> /// <returns>查詢結果(object)</returns> public static object ExecuteScalar(string sql, SqlParameter[] paras, string useDB = "") { SqlConnection conn = GetConnection(useDB); try { if (conn == null) throw new Exception(_linkErrMsg); conn.Open(); var cmd = new SqlCommand(sql, conn); cmd.CommandTimeout = CMDTimeOut; cmd.Parameters.Clear(); if (paras != null) { cmd.Parameters.AddRange(paras); } var obj = cmd.ExecuteScalar(); if (Object.Equals(obj, null) || Object.Equals(obj, System.DBNull.Value)) { return null; } else { return obj; } } catch (System.Data.SqlClient.SqlException e) { throw e; } finally { if (conn != null) conn.Close(); } } /// <summary> /// 執行查詢,並返回查詢所返回的結果集中第一行的第一列。忽略其他列或行。 /// </summary> /// <param name="trans">事務</param> /// <param name="sql">數據庫執行語句</param> /// <param name="cmdParms">參數集</param> /// <returns></returns> public static object ExecuteScalar(SqlTransaction trans, string sql, SqlParameter[] cmdParms = null) { try { if (trans.Connection.State == ConnectionState.Closed) { trans.Connection.Open(); } SqlCommand cmd = new SqlCommand(sql, trans.Connection); cmd.CommandTimeout = CMDTimeOut; cmd.Transaction = trans; cmd.Parameters.Clear(); if (cmdParms != null) { cmd.Parameters.AddRange(cmdParms); } var obj = cmd.ExecuteScalar(); if (Object.Equals(obj, null) || Object.Equals(obj, System.DBNull.Value)) { return null; } else { return obj; } } catch (Exception e) { throw e; } finally { trans.Connection.Close(); } } /// <summary> /// 執行查詢語句,返回DataSet /// </summary> /// <param name="sql">查詢語句</param> /// <param name="useDb">數據庫簡寫</param> /// <returns>數據集</returns> public static DataSet Query(string sql, string useDb = "") { var ds = new DataSet(); SqlConnection conn = GetConnection(useDb); try { if (conn == null) throw new Exception(_linkErrMsg); conn.Open(); SqlCommand cmd = new SqlCommand(sql, conn); cmd.CommandTimeout = CMDTimeOut; var command = new SqlDataAdapter(cmd); command.Fill(ds, _defaultDataSet); } catch (System.Data.SqlClient.SqlException e) { throw e; } finally { if (conn != null) conn.Close(); } return ds; } /// <summary> /// 執行查詢語句,返回DataSet(帶參數化) /// </summary> /// <param name="sql">sql語句</param> /// <param name="cmdParms">參數</param> /// <param name="useDb">數據庫簡寫</param> /// <returns>數據集</returns> public static DataSet QueryWithParams(string sql, SqlParameter[] cmdParms = null, string useDb = "") { var ds = new DataSet(); SqlConnection conn = GetConnection(useDb); try { if (conn == null) throw new Exception(_linkErrMsg); conn.Open(); SqlCommand cmd = new SqlCommand(sql, conn); cmd.CommandTimeout = CMDTimeOut; cmd.Parameters.Clear(); if (cmdParms != null) { cmd.Parameters.AddRange(cmdParms); } var command = new SqlDataAdapter(cmd); command.Fill(ds, _defaultDataSet); } catch (System.Data.SqlClient.SqlException e) { throw e; } finally { if (conn != null) conn.Close(); } return ds; } #region 存儲過程方法 /// <summary> /// 執行存儲過程 /// </summary> /// <param name="storedProcName">存儲過程名</param> /// <param name="parameters">存儲過程參數</param> /// <param name="useDB">數據庫簡寫</param> /// <param name="Times">超時時間</param> /// <returns>DataSet</returns> public static DataSet RunProcedure(string storedProcName, IDataParameter[] parameters, string useDB = "") { SqlConnection conn = GetConnection(useDB); try { if (conn == null) throw new Exception(_linkErrMsg); conn.Open(); DataSet dataSet = new DataSet(); SqlDataAdapter sqlDA = new SqlDataAdapter(); sqlDA.SelectCommand = BuildQueryCommand(conn, storedProcName, parameters); sqlDA.SelectCommand.CommandTimeout = CMDTimeOut; sqlDA.Fill(dataSet, _defaultDataTable); return dataSet; } finally { if (conn != null) conn.Close(); } } /// <summary> /// 構建 SqlCommand 對象(用來返回一個結果集,而不是一個整數值) /// </summary> /// <param name="connection">數據庫連接</param> /// <param name="storedProcName">存儲過程名</param> /// <param name="parameters">存儲過程參數</param> /// <returns>SqlCommand</returns> private static SqlCommand BuildQueryCommand(SqlConnection connection, string storedProcName, IDataParameter[] parameters) { SqlCommand command = new SqlCommand(storedProcName, connection); command.CommandType = CommandType.StoredProcedure; foreach (SqlParameter parameter in parameters) { if (parameter != null) { // 檢查未分配值的輸出參數,將其分配以DBNull.Value. if ((parameter.Direction == ParameterDirection.InputOutput || parameter.Direction == ParameterDirection.Input) && (parameter.Value == null)) { parameter.Value = DBNull.Value; } command.Parameters.Add(parameter); } } return command; } /// <summary> /// 執行存儲過程,返回請求結果 /// </summary> /// <param name="storedProcName">存儲過程名</param> /// <param name="parameters">存儲過程參數</param> /// <param name="rowsAffected">影響的行數</param> /// <returns>請求結果</returns> public static int RunProcedure(string storedProcName, IDataParameter[] parameters, out int rowsAffected, string useDB = "") { SqlConnection conn = GetConnection(useDB); try { rowsAffected = 0; if (conn == null) throw new Exception(_linkErrMsg); conn.Open(); int result; SqlCommand command = BuildIntCommand(conn, storedProcName, parameters); rowsAffected = command.ExecuteNonQuery(); result = (int)command.Parameters[_returnParaName].Value; return result; } finally { if (conn != null) conn.Close(); } } /// <summary> /// 創建 SqlCommand 對象實例(用來返回一個整數值) /// </summary> /// <param name="storedProcName">存儲過程名</param> /// <param name="parameters">存儲過程參數</param> /// <returns>SqlCommand 對象實例</returns> private static SqlCommand BuildIntCommand(SqlConnection connection, string storedProcName, IDataParameter[] parameters) { SqlCommand command = BuildQueryCommand(connection, storedProcName, parameters); command.Parameters.Add(new SqlParameter(_returnParaName, SqlDbType.Int, 4, ParameterDirection.ReturnValue, false, 0, 0, string.Empty, DataRowVersion.Default, null)); return command; } #endregion }
其次,常用的數據庫底層操作工具類整理:
/// <summary> /// 數據庫操作工具方法類 /// </summary> public class SqlTool { /// <summary> /// string擴展方法(忽略大小寫比較字符串) /// </summary> /// <param name="source">源字符串</param> /// <param name="value">目標字符串</param> /// <param name="comparisonType"></param> public static bool Contains(string source, string value, StringComparison comparisonType = StringComparison.OrdinalIgnoreCase) { return source.IndexOf(value, comparisonType) >= 0; } #region 校驗方法 /// <summary> /// 驗證sql匹配條件是否正確(若以and開頭則自動去除) /// </summary> /// <param name="where">sql匹配條件</param> public static string CheckWhere(string where) { if (!String.IsNullOrWhiteSpace(where)) { var str = where.TrimStart();//去除前置空格 if (str.IndexOf("and ", StringComparison.OrdinalIgnoreCase) == 0)//若以and開頭則自動去除第一個and { where = str.Substring(4);//若要保留前面一個空格,可以改為3 } //where = filterSql(where);//防SQL注入 if (str.IndexOf("order by", StringComparison.OrdinalIgnoreCase) == 0) { where = " " + where; } else if (!String.IsNullOrWhiteSpace(where)) { where = " where " + where; } } return where; } /// <summary> /// 表名安全校驗 /// </summary> /// <param name="tbName">數據表名</param> public static string CheckTbName(string tbName) { //if (tbName.Contains(" ") && !Contains(tbName, " join ")) //非連接語句 //{ // tbName = tbName.Replace(" ", "");//防止SQL注入 //} return tbName; } /// <summary> /// 字段安全校驗 /// </summary> /// <param name="fields">字段集合</param> public static string CheckFields(string fields) { //var str = fields.ToLower(); //if (fields.Contains(" ") && !str.Contains(",case ") && str.IndexOf("distinct ") < 0) //{ // str = str.Replace(" as ", "#"); // fields = str.Replace(" ", "").Replace("#", " as "); ;//防止SQL注入 //} return fields; } /// <summary> /// 過濾SQL語句,防止注入 /// </summary> /// <param name="strSql">Sql語句</param> public static string filterSql(string strSql) { var str = strSql.ToLower().Trim(); str = str.Replace("exec", ""); str = str.Replace("delete", ""); str = str.Replace("master", ""); str = str.Replace("truncate", ""); str = str.Replace("declare", ""); str = str.Replace("create", ""); str = str.Replace("xp_", "no"); return str; } #endregion #region 實體賦值方法 /// <summary> /// 類型轉換字典 /// </summary> private static Dictionary<Type, Type> TypeDic = new Dictionary<Type, Type>{{typeof(bool?),typeof(bool)},{typeof(int?),typeof(int)}, {typeof(long?),typeof(long)},{typeof(decimal?),typeof(decimal)},{typeof(DateTime?),typeof(DateTime)} }; /// <summary> /// 獲取標准類型 /// </summary> public static Type GetStandardType(Type t) { if (TypeDic.ContainsKey(t)) { t = TypeDic[t]; } return t; } /// <summary> /// 根據讀取到的數據為實體實例賦值 /// </summary> /// <typeparam name="T">實體</typeparam> /// <param name="dataReader">讀取到的一行數據</param> /// <param name="columns">數據列名集合</param> /// <param name="fields">實體屬性集合</param> /// <param name="info">實體實例</param> /// <returns>賦值后的實體實例</returns> public static T GetTValue<T>(IDataReader dataReader, List<string> columns, System.Reflection.PropertyInfo[] fields, T info) where T : class { try { var cols = new List<string>(); cols.AddRange(columns); foreach (var p in fields)//為實體實例賦值 { if (cols.Count < 1) break; var key = p.Name.ToLower(); var idx = cols.IndexOf(key); if (idx >= 0) { cols.RemoveAt(idx); var ovalue = dataReader[p.Name]; if (ovalue == null || ovalue == DBNull.Value) continue; var ptype = GetStandardType(p.PropertyType); p.SetValue(info, Convert.ChangeType(ovalue, ptype), null); } } } catch (Exception ex) { DbLog.LogErr("GetTValue方法異常:" + ex.Message); } return info; } /// <summary> /// 根據讀取到的數據為實體實例賦值 /// </summary> /// <typeparam name="T">實體</typeparam> /// <param name="row">數據行</param> /// <param name="columns">數據列名集合</param> /// <param name="fields">實體屬性集合</param> /// <param name="info">實體實例</param> /// <returns>賦值后的實體實例</returns> public static T GetTValue<T>(DataRow row, List<string> columns, System.Reflection.PropertyInfo[] fields, T info) where T : class { try { var cols = new List<string>(); cols.AddRange(columns); foreach (var p in fields)//為實體實例賦值 { if (cols.Count < 1) break; var key = p.Name.ToLower(); var idx = cols.IndexOf(key); if (idx >= 0) { cols.RemoveAt(idx); var ovalue = row[p.Name]; if (ovalue == null || ovalue == DBNull.Value) continue; var ptype = GetStandardType(p.PropertyType); p.SetValue(info, Convert.ChangeType(ovalue, ptype), null); } } } catch (Exception ex) { DbLog.LogErr("GetTValue1方法異常:" + ex.Message); } return info; } #endregion #region 實例工具方法 /// <summary> /// 對象實例緩存 /// </summary> private static System.Collections.Concurrent.ConcurrentDictionary<string, object> TCache = new System.Collections.Concurrent.ConcurrentDictionary<string, object>(); /// <summary> /// 緩存操作鎖 /// </summary> private static object lockCache = new object(); /// <summary> /// 實體克隆方法 /// </summary> private static MethodInfo wiseClone = typeof(object).GetMethod("MemberwiseClone", BindingFlags.NonPublic | BindingFlags.Instance); /// <summary> /// 實體克隆委托方法 /// </summary> public static Func<object, object> doClone = Delegate.CreateDelegate(typeof(Func<object, object>), wiseClone) as Func<object, object>; /// <summary> /// 獲取對象實例 /// </summary> /// <param name="type">對象類型</param> public static object GetInstance(Type type) { object obj; if (!TCache.TryGetValue(type.Name, out obj)) { obj = Activator.CreateInstance(type);//構建實例 lock (lockCache) { TCache.TryAdd(type.Name, obj); } } return obj; } /// <summary> /// DataSet轉實體集 /// </summary> /// <typeparam name="T">實體類</typeparam> public static List<T> DataSetToList<T>(DataSet ds) where T : class { if (ds != null) { var dt = ds.Tables[0]; return DataTableToList<T>(dt); } return new List<T>(); } /// <summary> /// DataTable轉實體集 /// </summary> /// <typeparam name="T">實體類</typeparam> public static List<T> DataTableToList<T>(DataTable dt) where T : class { var list = new List<T>(); if (dt != null && dt.Rows.Count > 0) { var type = typeof(T); var fields = type.GetProperties();//實體屬性集合 var columns = new List<string>();//數據列集合 int count = dt.Columns.Count; for (int i = 0; i < count; i++) { columns.Add(dt.Columns[i].ColumnName.ToLower()); } var obj = GetInstance(type); foreach (DataRow row in dt.Rows) { var val = GetTValue<T>(row, columns, fields, doClone(obj) as T); list.Add(val); } } return list; } #endregion }
SQL Server數據庫操作幫助類
/// <summary> /// SQL Server數據庫操作幫助類 /// </summary> public class MsSqlHelper { /// <summary> /// 參數前綴 /// </summary> private static string PreParameter = "@"; #region 工具方法 // <summary> /// 獲取數據插入SQL語句 /// </summary>性能:13字段十萬次約0.76s,49字段十萬次約1.81s /// <typeparam name="T">實體</typeparam> /// <param name="info">實體實例</param> /// <param name="tbName">數據表名(字段>=實體屬性)</param> /// <param name="sqlParams">SQL參數集</param> /// <param name="identify">第一個屬性是否為自增主鍵</param> /// <returns>數據插入SQL語句</returns> private static string GetInsertSQL<T>(T info, string tbName, out List<SqlParameter> sqlParams, bool identify = false) where T : class { var sql = String.Empty; sqlParams = new List<SqlParameter>();//返回值參數 if (String.IsNullOrWhiteSpace(tbName) || info == null) { return sql; } var type = typeof(T); var fields = type.GetProperties();//獲取實體成員字段 if (fields.Length < 2) //錯誤的數據實體 { return sql; } var fmt = "Insert into " + tbName + "({0}) values ({1});"; var cb = new StringBuilder(256);//列集合 var vb = new StringBuilder(512);//值集合 var link = ",";//字段連接符 var start = identify ? 1 : 0; var count = fields.Length; for (int i = start; i < count; i++) { var p = fields[i]; var v = p.GetValue(info, null); if (v == null || v == DBNull.Value) continue;//值為null不處理,使用數據庫默認值 cb.Append(link + p.Name); vb.Append(link + PreParameter + p.Name); sqlParams.Add(new SqlParameter(PreParameter + p.Name, v)); } if (cb.Length > 0) //實體屬性值不全為null { sql = string.Format(fmt, cb.Remove(0, 1).ToString(), vb.Remove(0, 1).ToString()); } return sql; } /// <summary> /// 獲取數據更新SQL語句(要求實體第一個屬性必須為主鍵) /// </summary> /// <typeparam name="T">實體</typeparam> /// <param name="info">實體實例</param> /// <param name="tbName">數據表名(字段>=實體屬性)</param> /// <param name="sqlParams">SQL參數集</param> /// <returns>數據更新SQL語句</returns> private static string GetUpdateSQL<T>(T info, string tbName, out List<SqlParameter> sqlParams) { var sql = String.Empty; sqlParams = new List<SqlParameter>();//返回值參數 if (String.IsNullOrWhiteSpace(tbName) || info == null) { return sql; } var type = typeof(T); var fields = type.GetProperties();//獲取實體成員字段 if (fields.Length < 2) //錯誤的數據實體 { return sql; } var cv = new StringBuilder(512);//列值對集合 var count = fields.Length; for (int i = 1; i < count; i++) { var p = fields[i]; var v = p.GetValue(info, null); if (v == null || v == DBNull.Value) continue;//值為null不處理,使用數據庫默認值 cv.Append("," + p.Name + "=" + PreParameter + p.Name); sqlParams.Add(new SqlParameter(PreParameter + p.Name, v)); } if (cv.Length > 0) //實體屬性值不全為null { var sets = cv.Remove(0, 1).ToString(); sqlParams.Add(new SqlParameter(PreParameter + fields[0].Name, fields[0].GetValue(info, null))); sql = string.Format("update {0} set {1} where " + fields[0].Name + "=" + PreParameter + fields[0].Name, tbName, sets); } return sql; } /// <summary> /// 獲取數據更新(先刪除后添加)SQL語句(要求實體第一個屬性必須為主鍵) /// </summary> /// <typeparam name="T">實體</typeparam> /// <param name="info">實體實例</param> /// <param name="tbName">數據表名(字段>=實體屬性)</param> /// <param name="sqlParams">SQL參數集</param> /// <param name="identify">第一個屬性是否為自增主鍵</param> /// <returns>數據更新SQL語句</returns> private static string GetUpdateByDelAndAdd<T>(T info, string tbName, out List<SqlParameter> sqlParams, bool identify = false) { var sql = String.Empty; sqlParams = new List<SqlParameter>();//返回值參數 if (String.IsNullOrWhiteSpace(tbName) || info == null) { return sql; } var type = typeof(T); var fields = type.GetProperties();//獲取實體成員字段 if (fields.Length < 2) //錯誤的數據實體 { return sql; } var sb = new StringBuilder(1024); sb.Append("delete from " + tbName + " where " + fields[0].Name + "=" + PreParameter + fields[0].Name); sb.Append("Insert into " + tbName + "({0}) values ({1});"); var cb = new StringBuilder(256);//列集合 var vb = new StringBuilder(512);//值集合 var link = ",";//字段連接符 var start = identify ? 1 : 0; var count = fields.Length; for (int i = start; i < count; i++) { var p = fields[i]; var v = p.GetValue(info, null); if (v == null || v == DBNull.Value) continue;//值為null不處理,使用數據庫默認值 cb.Append(link + p.Name); vb.Append(link + PreParameter + p.Name); sqlParams.Add(new SqlParameter(PreParameter + p.Name, v)); } if (cb.Length > 0) //實體屬性值不全為null { sql = string.Format(sb.ToString(), cb.Remove(0, 1).ToString(), vb.Remove(0, 1).ToString()); } return sql; } #endregion #region 取數據 /// <summary> /// 獲取指定表中指定列的值 /// </summary> /// <param name="ColumnCode">列編碼</param> /// <param name="tbName">數據表名</param> /// <param name="strWhere">匹配條件</param> /// <param name="useDb">數據庫簡寫</param> /// <returns>滿足條件的第一行的值</returns> public static string GetColumnValue(string ColumnCode, string tbName, string strWhere, string useDb = "") { var value = String.Empty; tbName = SqlTool.CheckTbName(tbName); ColumnCode = SqlTool.CheckFields(ColumnCode); if (String.IsNullOrEmpty(ColumnCode) || String.IsNullOrEmpty(tbName)) { return value; } var strSql = string.Format("select top 1 {0} from {1}", ColumnCode, tbName); strWhere = SqlTool.CheckWhere(strWhere); if (!String.IsNullOrWhiteSpace(strWhere)) { strSql += strWhere; } try { var obj = SqlBase.ExecuteScalar(strSql, useDb); value = obj == null ? String.Empty : obj.ToString(); } catch (Exception e) { DbLog.LogErr(string.Format("GetColumnValue方法異常:{0},表_{1} 字段_{2}", e.Message, tbName, ColumnCode)); } return value; } /// <summary> /// 獲取滿足條件的第一行多列的值 /// </summary> /// <param name="columns">列編碼集合</param> /// <param name="tbName">數據表名</param> /// <param name="strWhere">匹配條件</param> /// <param name="useDb">數據庫簡寫</param> /// <returns>滿足條件的首行多列的值</returns> public static List<string> GetValues(List<string> columns, string tbName, string strWhere, string useDb = "") { int step = 0; var value = new List<string>(); tbName = SqlTool.CheckTbName(tbName); if (columns.Count < 1 || String.IsNullOrEmpty(tbName)) { return value; } step = 1; var cols = SqlTool.CheckFields(string.Join(",", columns)); var strSql = string.Format("select top 1 {0} from {1}", cols, tbName); step = 2; strWhere = SqlTool.CheckWhere(strWhere); if (!String.IsNullOrWhiteSpace(strWhere)) { strSql += strWhere; } try { step = 3; var ds = SqlBase.Query(strSql, useDb); if (ds != null && ds.Tables[0] != null && ds.Tables[0].Rows.Count > 0) { var dr = ds.Tables[0].Rows[0]; var count = columns.Count; for (int i = 0; i < count; i++) { value.Add(dr[i] == null ? "" : dr[i].ToString()); } ds.Dispose(); } } catch (Exception e) { DbLog.LogErr(string.Format("GetValues方法異常:{0} step:{1} 表_{2} 字段_{3}", e.Message, step, tbName, cols)); } return value; } /// <summary> /// 獲取指定表中記錄總數 /// </summary> /// <param name="tbName">數據表名</param> /// <param name="strWhere">匹配條件</param> /// <param name="useDb">數據庫簡寫</param> /// <returns>滿足條件的記錄總數</returns> public static int GetRecordCount(string tbName, string strWhere, string useDb = "") { int value = 0; tbName = SqlTool.CheckTbName(tbName); if (String.IsNullOrEmpty(tbName)) { return value; } var strSql = string.Format("select count(1) from {0}", tbName); strWhere = SqlTool.CheckWhere(strWhere); if (!String.IsNullOrWhiteSpace(strWhere)) { strSql += strWhere; } try { object obj = SqlBase.ExecuteScalar(strSql, useDb); value = obj == null ? 0 : Convert.ToInt32(obj); } catch (Exception ex) { DbLog.LogErr(string.Format("GetRecordCount方法異常:{0},表_{1}", ex.Message, tbName)); } return value; } /// <summary> /// 獲取數據集 /// </summary> /// <param name="fields">列集合,形如:col1,col2,...,coln</param> /// <param name="tbName">數據表名</param> /// <param name="strWhere">匹配條件</param> /// <param name="top">獲取記錄最大數量,0為不限制</param> /// <param name="useDb">數據庫簡寫</param> /// <returns>滿足條件的數據集</returns> public static DataSet GetList(string fields, string tbName, string strWhere, int top = 0, string useDb = "") { DataSet ds = null; tbName = SqlTool.CheckTbName(tbName); fields = SqlTool.CheckFields(fields); if (String.IsNullOrEmpty(tbName)) { return ds; } var strSql = string.Format("select {0} {1} from {2}", top < 1 ? "" : string.Format("top {0}", top), String.IsNullOrEmpty(fields) ? "*" : fields, tbName); strWhere = SqlTool.CheckWhere(strWhere); if (!String.IsNullOrWhiteSpace(strWhere)) { strSql += strWhere; } try { ds = SqlBase.Query(strSql, useDb); } catch (Exception ex) { DbLog.LogErr(string.Format("GetList方法異常:{0},表_{1}", ex.Message, tbName)); } return ds; } /// <summary> /// 分頁獲取數據集 /// </summary> /// <param name="fields">列集合,形如:col1,col2,...,coln</param> /// <param name="tbName">數據表名</param> /// <param name="strWhere">匹配條件</param> /// <param name="orderby">排序字段 如:addtime desc</param> /// <param name="pageIndex">當前頁號</param> /// <param name="pageSize">每頁數據量</param> /// <param name="useDb">數據庫簡寫</param> /// <returns>滿足條件的數據集</returns> public static DataSet GetListByPage(string fields, string tbName, string strWhere, string orderby, int pageSize, int pageIndex, string useDb = "") { DataSet ds = null; tbName = SqlTool.CheckTbName(tbName); fields = SqlTool.CheckFields(fields); if (String.IsNullOrEmpty(fields) || String.IsNullOrEmpty(tbName) || String.IsNullOrEmpty(orderby)) { return ds; } if (pageSize < 1) pageSize = 10;//默認每頁10條 if (pageIndex < 1) pageIndex = 1;//默認第一頁 int start = (pageIndex - 1) * pageSize + 1; int end = pageIndex * pageSize; var strSql = new StringBuilder(512); strSql.Append("select * from ("); strSql.Append(string.Format("select ROW_NUMBER() OVER (ORDER BY {0}) as row,{1} from {2}", orderby, fields, tbName)); strWhere = SqlTool.CheckWhere(strWhere); if (!String.IsNullOrWhiteSpace(strWhere)) { strSql.Append(strWhere); } strSql.Append(string.Format(") as T where T.row between {0} and {1}", start, end)); try { ds = SqlBase.Query(strSql.ToString(), useDb); } catch (Exception ex) { DbLog.LogErr(string.Format("GetListByPage方法異常:{0},表_{1}", ex.Message, tbName)); } return ds; } /// <summary> /// 獲取對象實體 /// </summary> /// <typeparam name="T">實體類</typeparam> /// <param name="tbName">數據表名</param> /// <param name="strWhere">匹配條件</param> /// <param name="useDb">數據庫簡寫</param> /// <returns>數據實體</returns> public static T GetModel<T>(string tbName, string strWhere, string useDb = "") where T : class { return GetInfo<T>(tbName, strWhere, "*", useDb); } /// <summary> /// 獲取對象實體 /// </summary> /// <typeparam name="T">實體類</typeparam> /// <param name="tbName">數據表(可級聯)</param> /// <param name="fields">字段集合,形如:col1,col2,...,coln</param> /// <param name="strWhere">匹配條件</param> /// <param name="useDb">數據庫簡寫</param> /// <returns>數據實體</returns> public static T GetInfo<T>(string tbName, string strWhere, string fields = "*", string useDb = "") where T : class { T val = null; tbName = SqlTool.CheckTbName(tbName); fields = SqlTool.CheckFields(fields); if (!String.IsNullOrEmpty(tbName)) { var strSql = string.Format("select top 1 {0} from {1}", String.IsNullOrWhiteSpace(fields) ? "*" : fields, tbName); strWhere = SqlTool.CheckWhere(strWhere); if (!String.IsNullOrWhiteSpace(strWhere)) { strSql += strWhere; } try { var ds = SqlBase.Query(strSql, useDb); if (ds != null && ds.Tables.Count > 0) { var dt = ds.Tables[0]; if (dt != null && dt.Rows.Count > 0) { var columns = new List<string>();//數據列集合 var count = dt.Columns.Count; for (int i = 0; i < count; i++) { columns.Add(dt.Columns[i].ColumnName.ToLower()); } var type = typeof(T); var flist = type.GetProperties();//實體屬性集合 var obj = SqlTool.GetInstance(type); val = SqlTool.GetTValue<T>(dt.Rows[0], columns, flist, SqlTool.doClone(obj) as T); } } } catch (Exception ex) { DbLog.LogErr(string.Format("GetInfo方法異常:{0},表_{1}", ex.Message, tbName)); } } return val; } /// <summary> /// 獲取實體集合 /// </summary> /// <typeparam name="T">實體類</typeparam> /// <param name="tbName">數據表名</param> /// <param name="strWhere">匹配條件</param> /// <param name="top">要獲取的最大記錄數量,0為全部</param> /// <param name="cols">字段集合,形如:col1,col2,...,coln</param> /// <param name="useDb">數據庫簡寫</param> /// <returns>滿足條件的實體集</returns> public static List<T> GetInfoList<T>(string tbName, string strWhere, int top = 0, string cols = "*", string useDb = "") where T : class { try { var ds = GetList(cols, tbName, strWhere, top, useDb); return SqlTool.DataSetToList<T>(ds); } catch (Exception ex) { DbLog.LogErr(string.Format("GetInfoList方法異常:{0},表_{1}", ex.Message, tbName)); } return new List<T>(); } /// <summary> /// 分頁獲取實體集 /// </summary> /// <typeparam name="T">實體類</typeparam> /// <param name="tbName">數據表名</param> /// <param name="strWhere">匹配條件</param> /// <param name="orderby">排序字段 如:addtime desc</param> /// <param name="pageIndex">當前頁號</param> /// <param name="pageSize">每頁數據量</param> /// <param name="useDb">數據庫簡寫</param> /// <returns></returns> public static List<T> GetInfoByPage<T>(string tbName, string strWhere, string orderby, int pageSize, int pageIndex, string useDb = "") where T : class { try { var ds = GetListByPage("*", tbName, strWhere, orderby, pageSize, pageIndex, useDb); return SqlTool.DataSetToList<T>(ds); } catch (Exception ex) { DbLog.LogErr(string.Format("GetInfoByPage方法異常:{0},表_{1}", ex.Message, tbName)); } return new List<T>(); } /// <summary> /// 執行存儲過程,返回實體列表 /// </summary> /// <typeparam name="T">實體類</typeparam> /// <param name="storedProcName">存儲過程名</param> /// <param name="parameters">存儲過程參數</param> /// <param name="useDb">數據庫簡寫</param> /// <returns></returns> public static List<T> GetEntityList<T>(string storedProcName, IDataParameter[] parameters, string useDb = "") where T : class { try { var ds = SqlBase.RunProcedure(storedProcName, parameters, useDb); return SqlTool.DataSetToList<T>(ds); } catch (Exception ex) { DbLog.LogErr(string.Format("GetEntityList方法異常:{0},存儲過程名稱_{1}", ex.Message, storedProcName)); } return new List<T>(); } #endregion #region 添加數據 /// <summary> /// 添加記錄到數據庫(實體主鍵為自增整形)(帶事務) /// </summary> /// <typeparam name="T">實體(第一個屬性必須為自增主鍵)</typeparam> /// <param name="trans">事務(不使用時,傳入null)</param> /// <param name="info">實體實例</param> /// <param name="tbName">數據表名(字段>=實體屬性)</param> /// <returns>添加后生成的記錄ID</returns> public static long RecordAddIdentity<T>(SqlTransaction trans, T info, string tbName, string useDB = "") where T : class { var list = new List<SqlParameter>(); var sql = GetInsertSQL<T>(info, tbName.Replace(" ", ""), out list, true); if (!String.IsNullOrEmpty(sql)) { try { object obj; if (trans == null) { obj = SqlBase.ExecuteScalar(sql.TrimEnd(';') + ";Select @@IDENTITY", list.ToArray(), useDB); } else { obj = SqlBase.ExecuteScalar(trans, sql.TrimEnd(';') + ";Select @@IDENTITY", list.ToArray()); } return obj == null ? 0 : Convert.ToInt64(obj); } catch (Exception ex) { DbLog.LogErr(string.Format("RecordAddIdentity方法異常:{0},表_{1}", ex.Message, tbName)); } } return 0; } /// <summary> /// 添加記錄到數據庫(帶事務) /// </summary> /// <typeparam name="T">實體</typeparam> /// <param name="trans">事務(不使用時,傳入null)</param> /// <param name="info">實體實例</param> /// <param name="tbName">數據表名(字段>=實體屬性)</param> /// <returns>成功:True,失敗:False</returns> public static bool RecordAdd<T>(SqlTransaction trans, T info, string tbName, string useDB = "") where T : class { var list = new List<SqlParameter>(); var sql = GetInsertSQL<T>(info, tbName.Replace(" ", ""), out list); if (!String.IsNullOrEmpty(sql)) { try { int rows = 0; if (trans == null) { rows = SqlBase.ExecuteNonQuery(sql, list.ToArray(), useDB); } else { rows = SqlBase.ExecuteNonQuery(trans, sql, list.ToArray()); } return rows > 0; } catch (Exception ex) { DbLog.LogErr(string.Format("RecordAdd方法異常:{0},表_{1}", ex.Message, tbName)); } } return false; } /// <summary> /// 批量插入記錄(逐條) /// </summary> /// <typeparam name="T">實體</typeparam> /// <param name="trans">事務(不使用時,傳入null)</param> /// <param name="tbName">數據表名(字段>=實體屬性)</param> /// <param name="list">數據實體集合</param> /// <param name="identity">實體主鍵是否為自增整形</param> /// <param name="useDb">數據庫簡寫</param> /// <returns>執行成功的數據數</returns> public static int RecordsInsert<T>(SqlTransaction trans, string tbName, List<T> list, bool identity = false, string useDb = "") where T : class { int val = 0; var count = list.Count; if (identity) { for (int i = 0; i < count; i++) { if (RecordAddIdentity<T>(trans, list[i], tbName, useDb) > 0) { val++; } } } else { for (int i = 0; i < count; i++) { if (RecordAdd<T>(trans, list[i], tbName, useDb)) { val++; } } } return val; } /// <summary> /// 批量插入記錄(不支持html數據),不建議使用 /// </summary> /// <param name="tbName">數據表名</param> /// <param name="fields">字段集合 如:col1,col2,...</param> /// <param name="values">值集合(值中不能包含",") 如:'val1','val2',...</param> /// <param name="useDb">數據庫簡寫</param> /// <returns>受影響行數</returns> public static int RecordInsert(string tbName, string fields, List<string> values, string useDb = "") { if (String.IsNullOrWhiteSpace(tbName) || String.IsNullOrWhiteSpace(fields) || values.Count < 1) { return 0; } var strSql = new StringBuilder(512); strSql.Append(string.Format("insert into {0}({1}) ", tbName.Replace(" ", ""), fields.Replace(" ", ""))); var colLength = fields.Split(',').Length; var equalLength = false;//字段長度是否與值長度是否相同 var count = values.Count; for (int i = 0; i < count; i++) { if (values[i].Split(',').Length == colLength) { equalLength = true; if (i == 0) { strSql.Append(" select " + values[i]); } else { strSql.Append(" union all select " + values[i]); } } } if (equalLength) { try { return SqlBase.ExecuteNonQuery(strSql.ToString(), useDb); } catch (Exception ex) { DbLog.LogErr(string.Format("RecordInsert方法異常:{0},表_{1}", ex.Message, tbName)); } } return 0; } #endregion #region 更新數據 /// <summary> /// 更新指定數據庫指定表中信息 /// </summary>zlf 2014-12-10 /// <param name="trans">事務(不使用時,傳入null)</param> /// <param name="ColAndVal">列+值(形如:col = 'val',col2='val2')</param> /// <param name="tbName">數據表名</param> /// <param name="strWhere">匹配條件</param> /// <returns>是否更新成功</returns> public static bool SetValue(SqlTransaction trans, string ColAndVal, string tbName, string strWhere, string useDb = "") { bool value = false; if (ColAndVal.Contains(" ") && !SqlTool.Contains(ColAndVal, "case ")) { ColAndVal = ColAndVal.Replace(" ", "");//防止SQL注入 } if (String.IsNullOrEmpty(ColAndVal) || String.IsNullOrEmpty(tbName)) { return false; } var strSql = string.Format("update {0} set {1}", tbName.Replace(" ", ""), ColAndVal); strWhere = SqlTool.CheckWhere(strWhere); if (!String.IsNullOrEmpty(strWhere)) { strSql += strWhere; } try { int rows = 0; if (trans == null) { rows = SqlBase.ExecuteNonQuery(strSql, useDb); } else { rows = SqlBase.ExecuteNonQuery(trans, strSql); } return rows > 0; } catch (Exception ex) { DbLog.LogErr(string.Format("SetValue方法異常:{0},表_{1}", ex.Message, tbName)); } return value; } /// <summary> /// 更新一條記錄(實體第一個屬性必須為主鍵)(帶事務) /// </summary> /// <typeparam name="T">實體類 </typeparam> /// <param name="trans">事務(不使用時,傳入null)</param> /// <param name="tbName">數據表名(字段>=實體屬性)</param> /// <param name="info">數據實體</param> public static bool RecordUpdate<T>(SqlTransaction trans, string tbName, T info, string useDb = "") where T : class { var list = new List<SqlParameter>(); var sql = GetUpdateSQL<T>(info, tbName.Replace(" ", ""), out list); if (!String.IsNullOrEmpty(sql)) { try { int rows = 0; if (trans == null) { rows = SqlBase.ExecuteNonQuery(sql, list.ToArray(), useDb); } else { rows = SqlBase.ExecuteNonQuery(trans, sql, list.ToArray()); } return rows > 0; } catch (Exception ex) { DbLog.LogErr(string.Format("RecordUpdate方法異常:{0},表_{1}", ex.Message, tbName)); } } return false; } #endregion #region 刪除數據 /// <summary> /// 物理刪除數據行 /// </summary> /// <param name="trans">事務(不使用時,傳入null)</param> /// <param name="tbName">數據表名</param> /// <param name="strWhere">匹配條件</param> /// <param name="useDb">數據庫簡寫</param> public static bool DeleteRows(SqlTransaction trans, string tbName, string strWhere, string useDb = "") { var val = false; var strSql = string.Format("delete from {0}", tbName.Replace(" ", "")); strWhere = SqlTool.CheckWhere(strWhere); if (!String.IsNullOrEmpty(strWhere)) { strSql += strWhere; } else { return val; } try { int rows = 0; if (trans == null) { rows = SqlBase.ExecuteNonQuery(strSql, useDb); } else { rows = SqlBase.ExecuteNonQuery(trans, strSql); } return rows > 0; } catch (Exception ex) { DbLog.LogErr(string.Format("DeleteRows方法異常:{0},表_{1}", ex.Message, tbName)); } return val; } #endregion }
最后是操作日志類
/// <summary> /// 數據庫操作日志類 /// </summary> public class DbLog { /// <summary> /// 鎖 /// </summary> private static object lockObj = new object(); /// <summary> /// 日志路徑 /// </summary> private static string logPath = System.AppDomain.CurrentDomain.BaseDirectory + "DbLog\\"; /// <summary> /// 記錄運行日志 /// </summary> /// <param name="fileName">日志名稱</param> /// <param name="msg">日志信息</param> public static void WriteLog(string msg, string fileName) { //添加排他鎖,解決並發寫入的問題 System.Threading.Monitor.Enter(lockObj); try { fileName = string.Format("{0}_{1}", DateTime.Now.ToString("yyyyMMdd"), fileName); if (!System.IO.Directory.Exists(logPath)) { System.IO.Directory.CreateDirectory(logPath); } //如果日志文件大小超過了指定最大值,則轉存為新的文件 var fi = new System.IO.FileInfo(logPath + "\\" + fileName); if (fi.Exists && fi.Length >= 2 * 1024 * 1024) { fi.MoveTo(logPath + "\\" + DateTime.Now.ToString("yyyyMMddHHmmss") + "_long_" + fileName); } string logContent = msg; logContent = string.Format("{0} {1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"), msg); using (System.IO.StreamWriter SW = System.IO.File.AppendText(logPath + "\\" + fileName)) { SW.WriteLine(logContent); } } catch { return; } finally { System.Threading.Monitor.Exit(lockObj); } } /// <summary> /// 異步寫日志 /// </summary> public static void LogAsync(string msg, string fileName = "Db.log") { var logAsyn = new Action(() => { WriteLog(msg, fileName); }); logAsyn.BeginInvoke(null, null); } /// <summary> /// 記錄錯誤日志 /// </summary> /// <param name="msg">日志信息</param> public static void LogErr(string msg, string fileName = "Err.log") { LogAsync(msg, fileName); } }