/*
* 由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