/* * 由SharpDevelop创建。 * 用户:吴隆健 * 日期: 2019-03-21 * 时间: 10:07 * */ #if MMSQL using MrWu.Model; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace MrWu.DB { /// /// sqlServer 操作 /// public class MMSSQL : SqlEx { #region 属性与字段 /// /// 链接池 /// public override IConnectionPool connPool { get => null; // _ConnPool; } /// /// /// public string connectionString { get; } #endregion #region CTOR /// /// 初始化 /// /// public MMSSQL(SqlConfig config) { //this._ConnPool = new ConnectionPool(config); this.connectionString = string.Format("Data Source={0},{1};user id={2};pwd={3};Max Pool Size=512;initial catalog=", config.host, config.port, config.username, config.pwd); } #endregion #region SQL存储过程 /// /// 开始存储过程 /// /// 存储过程所在的数据库 /// 存储过程名 /// public override IProdureParameter BeginProcedure(string dbbase, string procedure) { //if (_ConnPool == null) // throw new Exception("you dont hava init"); SqlCommand cmd = new SqlCommand(procedure); //, GetConnection(dbbase) SqlProcedureParameter result = new SqlProcedureParameter(cmd, dbbase); //存储过程模式 cmd.CommandType = System.Data.CommandType.StoredProcedure; return result; } /// /// 添加参数 /// /// 存储过程查询键 /// 参数名 /// 参数值 /// 参数类型 /// 参数种类 public override void AddParam(IProdureParameter spp, string paramName, object value, SqlDbType type, ParameterDirection pd = ParameterDirection.Input) { if (spp == null || spp.command == null) throw new Exception("param spp null"); SqlParameter param = spp.command.Parameters.Add(paramName, type); param.Direction = pd; if (value == null) param.Value = DBNull.Value; else param.Value = value; } /// /// 提交存储过程 /// /// 存储过程查询键 /// 如果 存储过程中有查询表操作,则需要传递DataSet实例 /// 重试次数 小于0表示使用配置值 大于等于0表示自定义 /// 参数值,输出参数从字典中获取 public override Dictionary SubProcedure(IProdureParameter spp, DataSet ds = null, int againCount = -1) { if (spp == null || spp.command == null) throw new Exception("param spp null"); int cnt = Execute(spp.command, spp.dbName, ds, againCount); Dictionary dic = new Dictionary(); var pms = spp.command.Parameters; int len = pms.Count; for (int i = 0; i < len; i++) { dic.Add(pms[i].ParameterName, pms[i].Value); } if (!dic.ContainsKey(DbConst.RowsAffected)) { dic[DbConst.RowsAffected] = cnt; } spp.Dispose(); return dic; } #endregion #region SQL Query /// /// 执行sql语句 /// /// 数据库 /// sql语句 /// 单独设置sql语句的参数 一般用来设置二进制参数 或者过长的文字字符串 /// 重试次数 小于0表示使用配置值 大于等于0表示自定义 /// 如果是查询 使用传入ds实例 public override int ExecuteSql(string dbbase, string sql, IEnumerable sqlparams = null, DataSet ds = null, int againCount = -1) { SqlCommand cmd = new SqlCommand(sql); //, GetConnection(dbbase) cmd.CommandType = CommandType.Text; if (sqlparams != null) { //int len = sqlparams.Count(); //for (int i = 0; i < len; i++) { // ISqlAloneParameter sap = sqlparams[i]; // cmd.Parameters.Add(sap.paramname, sap.type, sap.valueLength); // cmd.Parameters[sap.paramname].Value = sap.paramvalue; //} foreach (var param in sqlparams) { cmd.Parameters.Add(param); } } return Execute(cmd, dbbase, ds, againCount); } /// /// 普通查询一个表 /// /// 数据库名称 /// 表名 /// 列名 /// 条件 /// 查询的数量 /// 重试次数 小于0表示使用配置值 大于等于0表示自定义 /// sql参数 /// 查询到的表 public override DataTable Select(string dbbase, string table, string[] column = null, string where = null, int count = 0, int againCount = -1, IEnumerable sqlparams = null) { StringBuilder sb = new StringBuilder(); sb.Append("select "); if (count > 0) { sb.Append(string.Format("Top {0} ", count)); } if (column != null && column.Length > 0) { int len = column.Length; for (int i = len - 1; i >= 0; i--) { sb.Append(column[i]); if (i > 0) sb.Append(","); } } else { sb.Append("*"); } sb.Append(" from "); sb.Append(table); if (!string.IsNullOrEmpty(where)) { sb.Append(" where "); sb.Append(where); } DataSet ds = new DataSet(); //Debug.Debug.Info("sql:" + sb.ToString()); ExecuteSql(dbbase, sb.ToString(), sqlparams, ds, againCount); if (ds.Tables == null || ds.Tables.Count == 0) return null; return ds.Tables[0]; } #endregion #region SQL 事务 /// /// 开始一个事务 /// /// 数据库 /// public override IProdureParameter BeginTransaction(string dbbase) { SqlCommand cmd = new SqlCommand(); SqlProcedureParameter spp = new SqlProcedureParameter(cmd, dbbase); try { var conn = GetConnection(dbbase); { conn.Open(); cmd.Connection = conn; cmd.Connection.ChangeDatabase(dbbase); cmd.Transaction = cmd.Connection.BeginTransaction(); //开始事务,还可以设置隔离等级 } } catch (Exception e) { spp.exception = e; if (cmd.Connection != null) { cmd.Connection.Dispose(); } } return spp; } /// /// 事务添加sql语句 /// /// /// /// public override int TransactionAddSql(IProdureParameter spp, string sql, List> sqlparams = null) { if (spp.isException) return 0; try { SqlCommand cmd = spp.command; cmd.CommandText = sql; cmd.Parameters.Clear(); if (sqlparams != null) { int len = sqlparams.Count; for (int i = 0; i < len; i++) { ISqlAloneParameter sap = sqlparams[i]; if (sap.valueLength > 0) cmd.Parameters.Add(sap.paramname, sap.type, sap.valueLength); else cmd.Parameters.Add(sap.paramname, sap.type); cmd.Parameters[sap.paramname].Value = sap.paramvalue; cmd.Parameters[sap.paramname].Direction = sap.Direction; } } var result = cmd.ExecuteNonQuery(); if (sqlparams != null) { for (int i = 0; i < sqlparams.Count; i++) { sqlparams[i].paramvalue = cmd.Parameters[i].Value; } } return result; } catch (Exception e) { spp.command.Transaction.Rollback(); //事务步骤异常,主动回滚事务 spp.exception = e; throw e; } } /// /// 提交事务 /// /// /// true 表示提交成功 false 表示提交失败 public override bool SubTransaction(IProdureParameter spp) { using (spp) { using (spp.command) { using (spp.command.Connection) { using (spp.command.Transaction) { try { spp.command.Transaction.Commit(); } catch (Exception e) { spp.exception = e; spp.command.Transaction.Rollback(); } return spp.exception == null; } } } } } /// /// 回滚事务 /// /// public override void RollbackTransaction(IProdureParameter spp) { try { spp.command.Transaction.Rollback(); //事务步骤异常,主动回滚事务 } catch (Exception ex) { Console.WriteLine(ex); } spp.command.Transaction?.Dispose(); spp.command.Connection?.Dispose(); spp.command.Dispose(); spp.Dispose(); } #endregion #region 异步方法 /// /// 异步提交存储过程 /// public override async Task> SubProcedureAsync(IProdureParameter spp, DataSet ds = null, int againCount = -1) { if (spp == null || spp.command == null) throw new Exception("param spp null"); int cnt = await ExecuteAsync(spp.command, spp.dbName, ds, againCount); Dictionary dic = new Dictionary(); var pms = spp.command.Parameters; int len = pms.Count; for (int i = 0; i < len; i++) { dic.Add(pms[i].ParameterName, pms[i].Value); } if (!dic.ContainsKey(DbConst.RowsAffected)) { dic[DbConst.RowsAffected] = cnt; } spp.Dispose(); return dic; } /// /// 异步执行sql语句 /// public override async Task ExecuteSqlAsync(string dbbase, string sql, IEnumerable sqlparams = null, DataSet ds = null, int againCount = -1) { SqlCommand cmd = new SqlCommand(sql); cmd.CommandType = CommandType.Text; if (sqlparams != null) { foreach (var param in sqlparams) { cmd.Parameters.Add(param); } } return await ExecuteAsync(cmd, dbbase, ds, againCount); } /// /// 异步查询 /// public override async Task SelectAsync(string dbbase, string table, string[] column = null, string where = null, int count = 0, int againCount = -1, IEnumerable sqlparams = null) { StringBuilder sb = new StringBuilder(); sb.Append("select "); if (count > 0) { sb.Append(string.Format("Top {0} ", count)); } if (column != null && column.Length > 0) { int len = column.Length; for (int i = len - 1; i >= 0; i--) { sb.Append(column[i]); if (i > 0) sb.Append(","); } } else { sb.Append("*"); } sb.Append(" from "); sb.Append(table); if (!string.IsNullOrEmpty(where)) { sb.Append(" where "); sb.Append(where); } DataSet ds = new DataSet(); await ExecuteSqlAsync(dbbase, sb.ToString(), sqlparams, ds, againCount); if (ds.Tables == null || ds.Tables.Count == 0) return null; return ds.Tables[0]; } /// /// 异步执行cmd /// public override async Task ExecuteAsync(SqlCommand cmd, string dbname, DataSet ds = null, int againCount = -1) { int result = 0; int exceCnt = 0; if (againCount < 0) againCount = errorTryAgainCount; while (exceCnt <= againCount) { try { using (cmd) { using (var conn = GetConnection(dbname)) { await conn.OpenAsync(); cmd.Connection = conn; cmd.Connection.ChangeDatabase(dbname); if (ds == null) { result = await cmd.ExecuteNonQueryAsync(); } else { using (var sda = new SqlDataAdapter()) { sda.SelectCommand = cmd; sda.Fill(ds); } } } } break; } catch (Exception e) { if (exceCnt < againCount) { Debug.Debug.Warning("数据库异步执行错误重试次数:" + exceCnt + ",错误类型:" + e.Message); } else { throw; } } int time = errorAgainTime + errorAgainTimeInc * exceCnt; exceCnt++; await Task.Delay(time); } return result; } #endregion #region SQL Common /// /// 获取一个连接 /// /// /// public override SqlConnection GetConnection(string dbbase) => new SqlConnection(connectionString + dbbase); /// /// 执行sql命令 /// /// /// 数据库名称 /// /// 重试次数 小于0表示使用配置值 大于等于0表示自定义 public override int Execute(SqlCommand cmd, string dbname, DataSet ds = null, int againCount = -1) { int result = 0; int exceCnt = 0; if (againCount < 0) againCount = errorTryAgainCount; while (exceCnt <= againCount) { try { using (cmd) { // Debug.Debug.Info("链接字符串:" + connectionString); using (var conn = GetConnection(dbname)) { conn.Open(); cmd.Connection = conn; cmd.Connection.ChangeDatabase(dbname); if (ds == null) { result = cmd.ExecuteNonQuery(); } else { using (var sda = new SqlDataAdapter()) { //一定要关闭,不然下次执行报错; sda.SelectCommand = cmd; sda.Fill(ds); //调用会自动执行 ExecuteNonQuery(); 不要重复调用,很容易出错! } } } } break; } catch (Exception e) { if (exceCnt < againCount) { Debug.Debug.Warning("数据库执行错误重试次数:" + exceCnt + ",错误类型:" + e.Message); } else { throw e; } } int time = errorAgainTime + errorAgainTimeInc * exceCnt; exceCnt++; //执行次数+1 Thread.Sleep(time); } return result; } #endregion } } #endif