feat: initial commit - HJHA game server full source

6 major server modules (PdkFriendServer/GlobalSever/ServerCore/GameModule/GameNetModule) +
game logic (GameFix/GameDAL/ServerData) +
network layer (NetWorkMessage) +
data layer (ObjectModel) +
utilities (MrWu/Core/Config/CloudAPI/dll) +
adapters (zyxAdapter/base)

.NET 8.0 C# solution, 16 projects, 958 source files
This commit is contained in:
2026-07-07 12:02:15 +08:00
commit e9616125ce
958 changed files with 158203 additions and 0 deletions

59
MrWu/DB/DataResult.cs Normal file
View File

@ -0,0 +1,59 @@
/********************************
*
* 作者:吴隆健
* 创建时间: 2019-06-06 16:07:29
*
********************************/
using System;
using System.Collections.Generic;
using System.Data;
namespace MrWu.DB {
/// <summary>
/// 定时器执行得到的数据结果集
/// </summary>
public class DataResult {
/// <summary>
/// 参数
/// </summary>
public Dictionary<string, object> pms { get; set; }
/// <summary>
/// 返回的数据集
/// </summary>
public DataSet data { get; set; }
/// <summary>
/// 数据结果集
/// </summary>
public DataResult() { }
/// <summary>
/// 数据结果集
/// </summary>
/// <param name="pms"></param>
public DataResult(Dictionary<string, object> pms) {
this.pms = pms;
}
/// <summary>
/// 数据结果集
/// </summary>
/// <param name="data"></param>
public DataResult(DataSet data) {
this.data = data;
}
/// <summary>
/// 数据结果集
/// </summary>
/// <param name="pms">存储过程参数</param>
/// <param name="data">返回的数据</param>
public DataResult(Dictionary<string, object> pms, DataSet data) {
this.pms = pms;
this.data = data;
}
}
}

7
MrWu/DB/DbConst.cs Normal file
View File

@ -0,0 +1,7 @@
namespace MrWu.DB
{
public static class DbConst
{
public const string RowsAffected = "RowsAffected";
}
}

View File

@ -0,0 +1,31 @@
/*
* 作者:吴隆健
* 日期: 2019-04-23
* 时间: 13:17
*
*/
using System;
using System.Collections.Concurrent;
using MrWu.Model;
namespace MrWu.DB {
/// <summary>
/// 连接池 T是链接类型
/// </summary>
public interface IConnectionPool<T> : IPool<T>{
/// <summary>
/// 链接字符串
/// </summary>
string connecStr {
get;
}
/// <summary>
/// 链接池
/// </summary>
ConcurrentQueue<T> conns {
get;
}
}
}

View File

@ -0,0 +1,45 @@
/*
* 作者:吴隆健
* 日期: 2019-04-23
* 时间: 13:17
*
*/
using System;
namespace MrWu.DB {
/// <summary>
/// 存储过程参数 T是指令类型
/// </summary>
public interface IProdureParameter<T> : IDisposable {
/// <summary>
/// 数据库名称
/// </summary>
string dbName {
get;
}
/// <summary>
/// sql命令
/// </summary>
T command {
get;
}
/// <summary>
/// 错误信息
/// </summary>
Exception exception {
get;
set;
}
/// <summary>
///
/// </summary>
bool isException {
get;
}
}
}

View File

@ -0,0 +1,49 @@
/*
* 作者:吴隆健
* 日期: 2019-04-23
* 时间: 13:21
*
*/
using System;
using System.Data;
namespace MrWu.DB {
/// <summary>
/// sql参数 T是数据类型
/// </summary>
public interface ISqlAloneParameter<T> {
/// <summary>
/// 参数名称
/// </summary>
string paramname {
get;
}
/// <summary>
/// 参数值
/// </summary>
object paramvalue {
get; set;
}
/// <summary>
/// 参数类型
/// </summary>
T type {
get;
}
/// <summary>
/// 值的长度
/// </summary>
int valueLength {
get;
}
/// <summary>
/// Direction
/// </summary>
ParameterDirection Direction { get; set; }
}
}

169
MrWu/DB/ISqlEx.cs Normal file
View File

@ -0,0 +1,169 @@
/*
* 作者:吴隆健
* 日期: 2019-04-23
* 时间: 13:17
*
*/
using System;
using System.Data;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Threading.Tasks;
namespace MrWu.DB {
/// <summary>
/// sql链接 T是sql的链接类型 K是指令类型 M是参数类型
/// </summary>
public interface ISqlEx<T,K,M,N> {
/// <summary>
/// 链接池
/// </summary>
IConnectionPool<T> connPool {
get;
}
/// <summary>
/// 获取一个连接
/// </summary>
/// <param name="dbbase"></param>
/// <returns></returns>
T GetConnection(string dbbase);
/// <summary>
/// 开始执行存储过程
/// </summary>
/// <param name="dbbase">数据库名称</param>
/// <param name="procedure">存储过程名称</param>
/// <returns></returns>
IProdureParameter<K> BeginProcedure(string dbbase,string procedure);
/// <summary>
/// 给存储过程添加参数
/// </summary>
/// <param name="spp">存储过程命令</param>
/// <param name="paramName">参数名</param>
/// <param name="value">参数值</param>
/// <param name="type">参数类型</param>
/// <param name="pd">参数种类</param>
void AddParam(IProdureParameter<K> spp,string paramName,object value,M type,ParameterDirection pd = ParameterDirection.Input);
/// <summary>
/// 提交存储过程
/// </summary>
/// <param name="spp">存储过程命令</param>
/// <param name="ds">查询的结果集</param>
/// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
/// <returns>执行存储过程所有参数</returns>
Dictionary<string, object> SubProcedure(IProdureParameter<K> spp, DataSet ds = null,int againCount = -1);
/// <summary>
/// 执行sql语句
/// </summary>
/// <param name="dbbase">数据库名称</param>
/// <param name="sql">sql语句</param>
/// <param name="sqlparams">sql的额外参数</param>
/// <param name="ds">查询的结果集</param>
/// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
/// <returns>受影响的行数</returns>
int ExecuteSql(string dbbase,string sql,IEnumerable<N> sqlparams = null,DataSet ds = null,int againCount = -1);
/// <summary>
/// 执行一个普通的查询
/// </summary>
/// <param name="dbbase">数据库名称</param>
/// <param name="table">数据库表名</param>
/// <param name="column">查询的列</param>
/// <param name="where">查询条件</param>
/// <param name="count">查询的行数</param>
/// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
/// <param name="sqlparams">sql参数</param>
/// <returns>查询的结果集</returns>
DataTable Select(string dbbase, string table, string[] column = null, string where = null, int count = 0,int againCount = -1, IEnumerable<N> sqlparams = null);
/// <summary>
/// 执行cmd
/// </summary>
/// <param name="cmd">数据库指令</param>
/// <param name="dbname">数据库名称</param>
/// <param name="ds">结果集</param>
/// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
/// <returns>受影响的行数</returns>
int Execute(K cmd,string dbname, DataSet ds = null,int againCount = -1);
/// <summary>
/// 执行一个事务
/// </summary>
/// <param name="dbbase">数据库名称</param>
/// <returns>存储过程指令</returns>
IProdureParameter<K> BeginTransaction(string dbbase);
/// <summary>
/// 为事务添加sql语句
/// </summary>
/// <param name="spp">存储过程指令</param>
/// <param name="sql">sql语句</param>
/// <param name="sqlparams">额外参数</param>
int TransactionAddSql(IProdureParameter<K> spp, string sql, List<ISqlAloneParameter<M>> sqlparams = null);
/// <summary>
/// 提交一个事务
/// </summary>
/// <param name="spp">存储过程指令</param>
/// <returns></returns>
bool SubTransaction(IProdureParameter<K> spp);
/// <summary>
/// 回滚事务
/// </summary>
/// <param name="spp"></param>
void RollbackTransaction(IProdureParameter<K> spp);
#region
/// <summary>
/// 异步提交存储过程
/// </summary>
/// <param name="spp">存储过程命令</param>
/// <param name="ds">查询的结果集</param>
/// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
/// <returns>执行存储过程所有参数</returns>
Task<Dictionary<string, object>> SubProcedureAsync(IProdureParameter<K> spp, DataSet ds = null, int againCount = -1);
/// <summary>
/// 异步执行sql语句
/// </summary>
/// <param name="dbbase">数据库名称</param>
/// <param name="sql">sql语句</param>
/// <param name="sqlparams">sql的额外参数</param>
/// <param name="ds">查询的结果集</param>
/// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
/// <returns>受影响的行数</returns>
Task<int> ExecuteSqlAsync(string dbbase, string sql, IEnumerable<N> sqlparams = null, DataSet ds = null, int againCount = -1);
/// <summary>
/// 异步执行一个普通的查询
/// </summary>
/// <param name="dbbase">数据库名称</param>
/// <param name="table">数据库表名</param>
/// <param name="column">查询的列</param>
/// <param name="where">查询条件</param>
/// <param name="count">查询的行数</param>
/// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
/// <param name="sqlparams">sql参数</param>
/// <returns>查询的结果集</returns>
Task<DataTable> SelectAsync(string dbbase, string table, string[] column = null, string where = null, int count = 0, int againCount = -1, IEnumerable<N> sqlparams = null);
/// <summary>
/// 异步执行cmd
/// </summary>
/// <param name="cmd">数据库指令</param>
/// <param name="dbname">数据库名称</param>
/// <param name="ds">结果集</param>
/// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
/// <returns>受影响的行数</returns>
Task<int> ExecuteAsync(K cmd, string dbname, DataSet ds = null, int againCount = -1);
#endregion
}
}

600
MrWu/DB/MMSSQL.cs Normal file
View File

@ -0,0 +1,600 @@
/*
* 由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
{
/// <summary>
/// sqlServer 操作
/// </summary>
public class MMSSQL : SqlEx<SqlConnection, SqlCommand, SqlDbType, SqlParameter>
{
#region
/// <summary>
/// 链接池
/// </summary>
public override IConnectionPool<SqlConnection> connPool
{
get => null; // _ConnPool;
}
/// <summary>
///
/// </summary>
public string connectionString { get; }
#endregion
#region CTOR
/// <summary>
/// 初始化
/// </summary>
/// <param name="config"></param>
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存储过程
/// <summary>
/// 开始存储过程
/// </summary>
/// <param name="dbbase">存储过程所在的数据库</param>
/// <param name="procedure">存储过程名</param>
/// <returns></returns>
public override IProdureParameter<SqlCommand> 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;
}
/// <summary>
/// 添加参数
/// </summary>
/// <param name="spp">存储过程查询键</param>
/// <param name="paramName">参数名</param>
/// <param name="value">参数值</param>
/// <param name="type">参数类型</param>
/// <param name="pd">参数种类</param>
public override void AddParam(IProdureParameter<SqlCommand> 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;
}
/// <summary>
/// 提交存储过程
/// </summary>
/// <param name="spp">存储过程查询键</param>
/// <param name="ds">如果 存储过程中有查询表操作,则需要传递DataSet实例</param>
/// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
/// <returns>参数值,输出参数从字典中获取</returns>
public override Dictionary<string, object> SubProcedure(IProdureParameter<SqlCommand> 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<string, object> dic = new Dictionary<string, object>();
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
/// <summary>
/// 执行sql语句
/// </summary>
/// <param name="dbbase">数据库</param>
/// <param name="sql">sql语句</param>
/// <param name="sqlparams">单独设置sql语句的参数 一般用来设置二进制参数 或者过长的文字字符串</param>
/// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
/// <param name="ds">如果是查询 使用传入ds实例</param>
public override int ExecuteSql(string dbbase, string sql, IEnumerable<SqlParameter> 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<SqlDbType> 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);
}
/// <summary>
/// 普通查询一个表
/// </summary>
/// <param name="dbbase">数据库名称</param>
/// <param name="table">表名</param>
/// <param name="column">列名</param>
/// <param name="where">条件</param>
/// <param name="count">查询的数量</param>
/// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
/// <param name="sqlparams">sql参数</param>
/// <returns>查询到的表</returns>
public override DataTable Select(string dbbase, string table, string[] column = null, string where = null,
int count = 0, int againCount = -1, IEnumerable<SqlParameter> 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
/// <summary>
/// 开始一个事务
/// </summary>
/// <param name="dbbase">数据库</param>
/// <returns></returns>
public override IProdureParameter<SqlCommand> 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;
}
/// <summary>
/// 事务添加sql语句
/// </summary>
/// <param name="spp"></param>
/// <param name="sql"></param>
/// <param name="sqlparams"></param>
public override int TransactionAddSql(IProdureParameter<SqlCommand> spp, string sql,
List<ISqlAloneParameter<SqlDbType>> 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<SqlDbType> 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;
}
}
/// <summary>
/// 提交事务
/// </summary>
/// <param name="spp"></param>
/// <returns>true 表示提交成功 false 表示提交失败</returns>
public override bool SubTransaction(IProdureParameter<SqlCommand> 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;
}
}
}
}
}
/// <summary>
/// 回滚事务
/// </summary>
/// <param name="spp"></param>
public override void RollbackTransaction(IProdureParameter<SqlCommand> 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
/// <summary>
/// 异步提交存储过程
/// </summary>
public override async Task<Dictionary<string, object>> SubProcedureAsync(IProdureParameter<SqlCommand> 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<string, object> dic = new Dictionary<string, object>();
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;
}
/// <summary>
/// 异步执行sql语句
/// </summary>
public override async Task<int> ExecuteSqlAsync(string dbbase, string sql,
IEnumerable<SqlParameter> 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);
}
/// <summary>
/// 异步查询
/// </summary>
public override async Task<DataTable> SelectAsync(string dbbase, string table, string[] column = null,
string where = null, int count = 0, int againCount = -1, IEnumerable<SqlParameter> 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];
}
/// <summary>
/// 异步执行cmd
/// </summary>
public override async Task<int> 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
/// <summary>
/// 获取一个连接
/// </summary>
/// <param name="dbbase"></param>
/// <returns></returns>
public override SqlConnection GetConnection(string dbbase) => new SqlConnection(connectionString + dbbase);
/// <summary>
/// 执行sql命令
/// </summary>
/// <param name="cmd"></param>
/// <param name="dbname">数据库名称</param>
/// <param name="ds"></param>
/// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
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

27
MrWu/DB/MethodType.cs Normal file
View File

@ -0,0 +1,27 @@
/*
* 作者:吴隆健
* 日期: 2019-04-07
* 时间: 20:05
*
*/
using System;
namespace MrWu.DB
{
/// <summary>
/// 方法类型
/// </summary>
public enum MethodType
{
/// <summary>
/// 过程
/// </summary>
Procedure = 0,
/// <summary>
/// 函数
/// </summary>
Function = 1,
}
}

691
MrWu/DB/MySQL.cs Normal file
View File

@ -0,0 +1,691 @@
#if MySQL
using System;
using System.Data;
using MySql.Data.MySqlClient;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using System.Text;
using System.Diagnostics;
using System.IO;
using MrWu.Model;
using System.Threading;
using MrWu.Debug;
using System.Data.SqlClient;
namespace MrWu.DB {
/// <summary>
/// mysql操作
/// </summary>
public class MySQL : SqlEx<MySqlConnection, MySqlCommand, MySqlDbType,MySqlParameter> {
/// <summary>
/// 链接池
/// </summary>
private class ConnectionPool : IConnectionPool<MySqlConnection> {
/// <summary>
/// 链接字符串
/// </summary>
private readonly string _connstr;
string IConnectionPool<MySqlConnection>.connecStr => _connstr;
private readonly int _capsize;
/// <summary>
/// 最大的缓存链接数量
/// </summary>
int IPool<MySqlConnection>.capSize => _capsize;
private readonly int _surviveCountSize;
/// <summary>
/// 同时存在最大的链接数量
/// </summary>
/// <returns></returns>
int IPool<MySqlConnection>.surviveCountSize => _surviveCountSize;
/// <summary>
/// 当前池中的数量
/// </summary>
int IPool<MySqlConnection>.capCount => _conns.Count;
long _surviveCount = 0;
/// <summary>
/// 当前存活数量
/// </summary>
int IPool<MySqlConnection>.surviveCount {
get {
return (int)Interlocked.Read(ref _surviveCount);
}
}
/// <summary>
/// 所有的链接
/// </summary>
private readonly ConcurrentQueue<MySqlConnection> _conns = new ConcurrentQueue<MySqlConnection>();
ConcurrentQueue<MySqlConnection> IConnectionPool<MySqlConnection>.conns => _conns;
/// <summary>
/// 用于异步等待连接可用的信号量
/// </summary>
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1);
public ConnectionPool(SqlConfig config) {
this._capsize = config.cacheCount;
this._surviveCountSize = config.surviveCountSize;
this._connstr = string.Format("server={0};port={1};user={2};password={3};AllowUserVariables={4};pooling=true;database=",
config.host, config.port, config.username, config.pwd, config.AllowUserVariables);
}
/// <summary>
/// 获取一个连接
/// </summary>
/// <param name="dbbase"></param>
/// <returns></returns>
public MySqlConnection TakeOut(params object[] dbbase) {
if (dbbase.Length <= 0) return null;
string dbname = dbbase[0] as string;
if (dbname == null) return null;
MySqlConnection conn;
if (_conns.TryDequeue(out conn)) {
if (conn != null) {
return conn;
}
}
if (this._surviveCountSize > 0 && Interlocked.Read(ref _surviveCount) >= this._surviveCountSize)
return null;
Interlocked.Increment(ref _surviveCount);
return new MySqlConnection(this._connstr + dbname);
}
/// <summary>
/// 异步获取一个连接(连接池满时不会阻塞线程)
/// </summary>
public async Task<MySqlConnection> TakeOutAsync(string dbname) {
if (dbname == null) return null;
while (true) {
MySqlConnection conn;
if (_conns.TryDequeue(out conn)) {
if (conn != null) return conn;
}
if (this._surviveCountSize == 0 || Interlocked.Read(ref _surviveCount) < this._surviveCountSize) {
Interlocked.Increment(ref _surviveCount);
return new MySqlConnection(this._connstr + dbname);
}
// 连接池满,异步等待
await _semaphore.WaitAsync();
_semaphore.Release();
}
}
/// <summary>
/// 放入一个连接
/// </summary>
/// <param name="conn"></param>
public void PutInto(MySqlConnection conn) {
if (_capsize == 0 || _conns.Count < _capsize) {
_conns.Enqueue(conn);
} else {
conn.Dispose();
Interlocked.Decrement(ref _surviveCount);
}
}
}
/*
* 1.执行sql语句 获得执行sql语句后的结果
* 2.执行存储过程 获得存储过程的结果
*
* 每个库都有一个链接
*
* */
private ConnectionPool _ConnPool = null;
/// <summary>
/// 链接池
/// </summary>
public override IConnectionPool<MySqlConnection> connPool => _ConnPool;
/// <summary>
/// 初始化
/// </summary>
/// <param name="config"></param>
public MySQL(SqlConfig config) {
this._ConnPool = new ConnectionPool(config);
errorTryAgainCount = config.errorTryAgainCount;
errorAgainTimeInc = config.errorAgainTimeInc;
errorAgainTime = config.errorAgainTime;
if (errorTryAgainCount < 0)
throw new ArgumentException("errorTryAgainCount 不能小于 0");
if (errorAgainTimeInc < 0)
throw new ArgumentException("errorAgainTimeInc 不能小于 0");
if (errorAgainTime < 0)
throw new ArgumentException("errorAgainTime 不能小于 0");
}
/// <summary>
/// 获取一个连接
/// </summary>
/// <param name="dbbase"></param>
/// <returns></returns>
public override MySqlConnection GetConnection(string dbbase) {
MySqlConnection tmp;
while (true) {
tmp = _ConnPool.TakeOut(dbbase);
if (tmp != null)
return tmp;
Debug.Debug.Warning("链接数超过上限,等待重试");
Thread.Sleep(2);
}
}
/// <summary>
/// 异步获取一个连接(不会阻塞线程)
/// </summary>
public async Task<MySqlConnection> GetConnectionAsync(string dbbase) {
return await _ConnPool.TakeOutAsync(dbbase);
}
/// <summary>
/// 开始存储过程
/// </summary>
/// <param name="dbbase">存储过程所在的数据库</param>
/// <param name="procedure">存储过程名</param>
/// <returns></returns>
public override IProdureParameter<MySqlCommand> BeginProcedure(string dbbase, string procedure) {
if (_ConnPool == null)
throw new Exception("you dont hava init");
MySqlCommand cmd = new MySqlCommand(procedure, GetConnection(dbbase));
MySqlProcedureParameter result = new MySqlProcedureParameter(cmd, dbbase);
//存储过程模式
cmd.CommandType = CommandType.StoredProcedure;
return result;
}
/// <summary>
/// 添加参数
/// </summary>
/// <param name="spp">存储过程查询键</param>
/// <param name="paramName">参数名</param>
/// <param name="value">参数值</param>
/// <param name="type">参数类型</param>
/// <param name="pd">参数种类</param>
public override void AddParam(IProdureParameter<MySqlCommand> spp, string paramName, object value, MySqlDbType type, ParameterDirection pd = ParameterDirection.Input) {
if (spp == null || spp.command == null)
throw new Exception("param spp null");
MySqlParameter param = spp.command.Parameters.Add(paramName, type);
param.Direction = pd;
if (value == null)
param.Value = DBNull.Value;
else
param.Value = value;
}
/// <summary>
/// 提交存储过程
/// </summary>
/// <param name="spp">存储过程查询键</param>
/// <param name="ds">如果 存储过程中有查询表操作,则需要传递DataSet实例</param>
/// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
/// <returns>参数值,输出参数从字典中获取</returns>
public override Dictionary<string, object> SubProcedure(IProdureParameter<MySqlCommand> 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<string, object> dic = new Dictionary<string, object>();
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;
}
/// <summary>
/// 执行sql语句
/// </summary>
/// <param name="dbbase">数据库</param>
/// <param name="sql">sql语句</param>
/// <param name="mysqlparams"></param>
/// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
/// <param name="ds">如果是查询 使用传入ds实例</param>
public override int ExecuteSql(string dbbase, string sql, IEnumerable<MySqlParameter> mysqlparams = null, DataSet ds = null, int againCount = -1) {
MySqlCommand cmd = new MySqlCommand(sql, GetConnection(dbbase));
cmd.CommandType = CommandType.Text;
if (mysqlparams != null) {
//int len = mysqlparams.Count;
//for (int i = 0; i < len; i++) {
// ISqlAloneParameter<MySqlDbType> msap = mysqlparams[i];
// cmd.Parameters.Add(msap.paramname, msap.type, msap.valueLength);
// cmd.Parameters[msap.paramname].Value = msap.paramvalue;
//}
foreach (var param in mysqlparams) {
cmd.Parameters.Add(param);
}
}
return Execute(cmd, dbbase, ds, againCount);
}
/// <summary>
/// 执行sql语句
/// </summary>
/// <param name="dbbase">数据库</param>
/// <param name="sql">sql语句</param>
/// <param name="mysqlparams">附加参数</param>
/// <returns></returns>
public MySqlCommand GetCommandBySql(string dbbase, string sql, IEnumerable<MySqlParameter> mysqlparams = null) {
MySqlCommand cmd = new MySqlCommand(sql, GetConnection(dbbase));
cmd.CommandType = CommandType.Text;
if (mysqlparams != null) {
//int len = mysqlparams.Count;
//for (int i = 0; i < len; i++) {
// ISqlAloneParameter<MySqlDbType> msap = mysqlparams[i];
// cmd.Parameters.Add(msap.paramname, msap.type, msap.valueLength);
// cmd.Parameters[msap.paramname].Value = msap.paramvalue;
//}
foreach (var param in mysqlparams) {
cmd.Parameters.Add(param);
}
}
return cmd;
}
/// <summary>
/// 普通查询一个表
/// </summary>
/// <param name="dbbase">数据库名称</param>
/// <param name="table">表名</param>
/// <param name="column">列名</param>
/// <param name="where">条件</param>
/// <param name="count">查询的数量</param>
/// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
/// <param name="sqlparams">sqlparams</param>
/// <returns>查询到的表</returns>
public override DataTable Select(string dbbase, string table, string[] column = null, string where = null, int count = 0, int againCount = -1, IEnumerable<MySqlParameter> sqlparams = null) {
StringBuilder sb = new StringBuilder();
sb.Append("select ");
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);
}
if (count > 0) {
sb.AppendFormat(" limit {0}", count);
}
DataSet ds = new DataSet();
ExecuteSql(dbbase, sb.ToString(), sqlparams, ds, againCount);
if (ds.Tables == null || ds.Tables.Count == 0)
return null;
return ds.Tables[0];
}
/// <summary>
/// 执行sql命令
/// </summary>
/// <param name="cmd">指令</param>
/// <param name="dbname">数据库名称</param>
/// <param name="ds">null表示不需要查询结果集 有值将会把结果集放到 ds中</param>
/// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
public override int Execute(MySqlCommand cmd, string dbname, DataSet ds = null, int againCount = -1) {
// Debug.Debug.Log("执行sql指令!");
int result = 0;
int exceCnt = 0; //执行次数
//重试次数
if (againCount < 0)
againCount = errorTryAgainCount;
try {
while (exceCnt <= againCount) {
try {
if (cmd.Connection.State == ConnectionState.Closed)
cmd.Connection.Open();
cmd.Connection.ChangeDatabase(dbname);
if (ds == null)
result = cmd.ExecuteNonQuery();
else {
using(MySqlDataAdapter sda = new MySqlDataAdapter()) {
sda.SelectCommand = cmd;
sda.Fill(ds);
}
}
break;
} catch (Exception e) {
cmd.Connection.Close();
if (exceCnt < againCount)
Debug.Debug.Error("数据库执行错误重试次数:" + exceCnt + ",错误类型:" + e.Message);
else
throw e;
}
int time = errorAgainTime + errorAgainTimeInc * exceCnt;
exceCnt++; //执行次数+1
Thread.Sleep(time);
}
} finally {
_ConnPool.PutInto(cmd.Connection); //放入链接
}
return result;
}
/// <summary>
/// 开始一个事务
/// </summary>
/// <param name="dbbase">数据库</param>
/// <returns></returns>
public override IProdureParameter<MySqlCommand> BeginTransaction(string dbbase) {
MySqlCommand cmd = new MySqlCommand();
MySqlProcedureParameter spp = new MySqlProcedureParameter(cmd, dbbase);
try {
cmd.Connection = GetConnection(dbbase);
if (cmd.Connection.State == ConnectionState.Closed)
cmd.Connection.Open();
cmd.Connection.ChangeDatabase(dbbase);
cmd.Transaction = cmd.Connection.BeginTransaction(); //开始事务,还可以设置隔离等级
} catch (Exception e) {
spp.exception = e;
}
return spp;
}
/// <summary>
/// 事务添加sql语句
/// </summary>
/// <param name="spp"></param>
/// <param name="sql"></param>
/// <param name="sqlparams"></param>
public override int TransactionAddSql(IProdureParameter<MySqlCommand> spp, string sql, List<ISqlAloneParameter<MySqlDbType>> sqlparams = null) {
if (spp.isException)
return 0;
try {
MySqlCommand cmd = spp.command;
cmd.CommandText = sql;
cmd.Parameters.Clear();
if (sqlparams != null) {
int len = sqlparams.Count;
for (int i = 0; i < len; i++) {
ISqlAloneParameter<MySqlDbType> sap = sqlparams[i];
cmd.Parameters.Add(sap.paramname, sap.type, sap.valueLength);
cmd.Parameters[sap.paramname].Value = sap.paramvalue;
}
}
return cmd.ExecuteNonQuery();
} catch (Exception e) {
spp.exception = e;
throw e;
}
}
/// <summary>
/// 提交事务
/// </summary>
/// <param name="spp"></param>
/// <returns>true 表示提交成功 false 表示提交失败</returns>
public override bool SubTransaction(IProdureParameter<MySqlCommand> spp) {
try {
spp.command.Transaction.Commit();
} catch (Exception e) {
spp.exception = e;
spp.command.Transaction.Rollback();
} finally {
_ConnPool.PutInto(spp.command.Connection);
spp.Dispose();
}
return spp.exception == null;
}
/// <summary>
/// 回滚事务
/// </summary>
/// <param name="spp"></param>
public override void RollbackTransaction(IProdureParameter<MySqlCommand> spp) {
try {
spp.command.Transaction.Rollback();
} catch (Exception ex) {
Debug.Debug.Error("RollbackTransaction ex: " + ex);
}
}
#region
/// <summary>
/// 异步提交存储过程
/// </summary>
public override async Task<Dictionary<string, object>> SubProcedureAsync(IProdureParameter<MySqlCommand> 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<string, object> dic = new Dictionary<string, object>();
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;
}
/// <summary>
/// 异步执行sql语句
/// </summary>
public override async Task<int> ExecuteSqlAsync(string dbbase, string sql, IEnumerable<MySqlParameter> mysqlparams = null, DataSet ds = null, int againCount = -1) {
MySqlCommand cmd = new MySqlCommand(sql, await GetConnectionAsync(dbbase));
cmd.CommandType = CommandType.Text;
if (mysqlparams != null) {
foreach (var param in mysqlparams) {
cmd.Parameters.Add(param);
}
}
return await ExecuteAsync(cmd, dbbase, ds, againCount);
}
/// <summary>
/// 异步查询
/// </summary>
public override async Task<DataTable> SelectAsync(string dbbase, string table, string[] column = null, string where = null, int count = 0, int againCount = -1, IEnumerable<MySqlParameter> sqlparams = null) {
StringBuilder sb = new StringBuilder();
sb.Append("select ");
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);
}
if (count > 0) {
sb.AppendFormat(" limit {0}", count);
}
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];
}
/// <summary>
/// 异步执行sql命令
/// </summary>
public override async Task<int> ExecuteAsync(MySqlCommand cmd, string dbname, DataSet ds = null, int againCount = -1) {
int result = 0;
int exceCnt = 0;
if (againCount < 0)
againCount = errorTryAgainCount;
try {
while (exceCnt <= againCount) {
try {
if (cmd.Connection.State == ConnectionState.Closed)
await cmd.Connection.OpenAsync();
cmd.Connection.ChangeDatabase(dbname);
if (ds == null)
result = await cmd.ExecuteNonQueryAsync();
else {
using(MySqlDataAdapter sda = new MySqlDataAdapter()) {
sda.SelectCommand = cmd;
sda.Fill(ds);
}
}
break;
} catch (Exception e) {
cmd.Connection.Close();
if (exceCnt < againCount)
Debug.Debug.Error("数据库异步执行错误重试次数:" + exceCnt + ",错误类型:" + e.Message);
else
throw;
}
int time = errorAgainTime + errorAgainTimeInc * exceCnt;
exceCnt++;
await Task.Delay(time);
}
} finally {
_ConnPool.PutInto(cmd.Connection);
}
return result;
}
#endregion
/// <summary>
/// 保存每个存储过程为单个文件
/// </summary>
/// <param name="dbbase">那个数据库的</param>
/// <param name="path">存储的路径</param>
/// <param name="method">如果导出其中一个存储过程,则填存储过程名称</param>
public void SaveMethod(string dbbase, string path, string method = null) {
DataTable dt;
if (method == null)
dt = Select("information_schema", "routines", new string[] { "routine_name", "routine_type" }, string.Format("routine_schema='{0}'", dbbase));
else
dt = Select("information_schema", "routines", new string[] { "routine_name", "routine_type" }, string.Format("routine_schema='{0}' and routine_name='{1}'", dbbase, method));
foreach (DataColumn item in dt.Columns) {
Console.WriteLine(item.ColumnName);
}
int len = dt.Rows.Count;
for (int i = 0; i < len; i++) {
SaveMethod(dbbase, path, dt.Rows[i]["routine_name"] as string, dt.Rows[i]["routine_type"] as string);
}
}
/// <summary>
/// 保存方法
/// </summary>
/// <param name="dbbase"></param>
/// <param name="path"></param>
/// <param name="methodName"></param>
/// <param name="methodType"></param>
private void SaveMethod(string dbbase, string path, string methodName, string methodType) {
if (!Directory.Exists(path)) {
Directory.CreateDirectory(path);
}
string sql = string.Format("show create {0} {1};", methodType, methodName);
DataSet ds = new DataSet();
ExecuteSql(dbbase, sql, null, ds);
if (ds.Tables == null || ds.Tables.Count == 0 || ds.Tables[0].Rows == null || ds.Tables[0].Rows.Count == 0)
return;
path = string.Format("{0}/{1}.sql", path, methodName);
string sqlCode = string.Format("Drop {0} if exists {1};{2}", methodType, methodName, Environment.NewLine);
sqlCode += "Commit;" + Environment.NewLine;
sqlCode += ds.Tables[0].Rows[0][string.Format("Create {0}", methodType)] as string;
File.WriteAllText(path, sqlCode, Encoding.UTF8);
}
/// <summary>
/// 执行sql文件
/// </summary>
/// <param name="dbbase"></param>
/// <param name="path"></param>
public void Execute(string dbbase, string path) {
if (File.Exists(path)) {
try {
string sql = File.ReadAllText(path);
ExecuteSql(dbbase, sql);
} catch (Exception e) {
Console.WriteLine("运行出错:" + path + Environment.NewLine + e.ToString());
}
} else if (Directory.Exists(path)) {
DirectoryInfo dinfo = new DirectoryInfo(path);
string[] paths = Directory.GetDirectories(path);
foreach (var item in paths) {
Console.WriteLine(item);
Execute(dbbase, item);
}
FileInfo[] finfos = dinfo.GetFiles();
foreach (var fl in finfos) {
Execute(dbbase, fl.FullName);
}
}
}
}
}
#endif

View File

@ -0,0 +1,130 @@
#if MySQL
using System;
using System.Data;
using MySql.Data.MySqlClient;
namespace MrWu.DB {
/// <summary>
/// 存储过程查询键
/// </summary>
public class MySqlProcedureParameter : IProdureParameter<MySqlCommand> {
MySqlCommand _command;
/// <summary>
/// 指令
/// </summary>
public MySqlCommand command {
get => _command;
}
private string _dbName;
/// <summary>
/// 数据库名称
/// </summary>
public string dbName {
get => _dbName;
}
/// <summary>
/// 错误信息
/// </summary>
public Exception exception {
get;
set;
}
/// <summary>
/// 是否报错
/// </summary>
public bool isException {
get {
return exception != null;
}
}
private MySqlProcedureParameter() { }
internal MySqlProcedureParameter(MySqlCommand mysqlcommand,string dbName) {
this._command = mysqlcommand;
this._dbName = dbName;
}
/// <summary>
/// 释放
/// </summary>
public void Dispose() {
if (_command != null) {
_command.Dispose();
_command = null;
}
}
}
/// <summary>
/// 单独设置参数
/// </summary>
public class MySqlAloneParameter : ISqlAloneParameter<MySqlDbType> {
string _paramname;
/// <summary>
/// 参数名称
/// </summary>
public string paramname {
get => _paramname;
}
object _parmavalue;
/// <summary>
/// 参数值
/// </summary>
public object paramvalue {
get => _parmavalue;
set => _parmavalue = value;
}
MySqlDbType _type;
/// <summary>
/// 参数类型
/// </summary>
public MySqlDbType type {
get => _type;
}
int _valueLength;
/// <summary>
/// 参数长度
/// </summary>
public int valueLength {
get => _valueLength;
}
/// <summary>
/// sql语句单独设置参数
/// </summary>
/// <param name="paramname">参数名称</param>
/// <param name="paramvalue">参数值</param>
/// <param name="valuelength">参数值的长度</param>
/// <param name="type">参数类型</param>
public MySqlAloneParameter(string paramname, object paramvalue, int valuelength, MySqlDbType type = MySqlDbType.Binary) {
this._paramname = paramname;
this._parmavalue = paramvalue;
this._valueLength = valuelength;
this._type = type;
}
/// <summary>
/// Direction
/// </summary>
public ParameterDirection Direction { get; set; }
}
}
#endif

146
MrWu/DB/SqlConfig.cs Normal file
View File

@ -0,0 +1,146 @@
/*
* 由SharpDevelop创建。
* 用户: Administrator
* 日期: 2019-03-21
* 时间: 10:10
*
* 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件
*/
using System;
using System.Net;
namespace MrWu.DB {
/// <summary>
/// sql 配置
/// </summary>
public class SqlConfig {
/// <summary>
/// 配置名称
/// </summary>
public string name {
get;
set;
}
/// <summary>
///
/// </summary>
public string host {
get;
set;
}
/// <summary>
/// 端口
/// </summary>
public int port {
get;
set;
}
/// <summary>
/// 用户名
/// </summary>
public string username {
get;
set;
}
/// <summary>
/// 密码
/// </summary>
public string pwd {
get;
set;
}
/// <summary>
/// 版本
/// </summary>
public string verison {
get;
set;
}
/// <summary>
/// 是否允许使用会话变量
/// </summary>
public bool AllowUserVariables {
get;
set;
}
private int errorTryAgainCount_ = 5;
/// <summary>
/// 出错重试次数 0表示不重试
/// </summary>
public int errorTryAgainCount {
get {
return errorTryAgainCount_;
}
set {
errorTryAgainCount_ = value;
}
}
/// <summary>
/// 出错重试时间增量 单位毫秒 0表示以固定时间间隔重试
/// </summary>
public int errorAgainTimeInc {
get;
set;
}
/// <summary>
/// 不启用SSL模式
/// </summary>
public string sslMode = "None";
private int _errorAginTime = 100;
/// <summary>
/// 执行出错,第一次多少毫秒后进行重试
/// </summary>
public int errorAgainTime {
get {
return _errorAginTime;
}
set {
_errorAginTime = value;
}
}
private int _cacheCount = 10;
/// <summary>
/// 缓存链接数量
/// </summary>
public int cacheCount {
get {
return _cacheCount;
}
set {
_cacheCount = value;
}
}
/// <summary>
/// 限制链接数量
/// </summary>
private int _surviveCountSize = 0;
/// <summary>
/// 最大存活链接数
/// </summary>
public int surviveCountSize {
get {
return _surviveCountSize;
}
set {
_surviveCountSize = value;
}
}
}
}

173
MrWu/DB/SqlEx.cs Normal file
View File

@ -0,0 +1,173 @@
/********************************
*
* 作者:吴隆健
* 创建时间: 2019-06-06 13:34:46
*
********************************/
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Threading.Tasks;
namespace MrWu.DB {
/// <summary>
/// sql链接
/// </summary>
/// <typeparam name="T">T是sql的链接类型</typeparam>
/// <typeparam name="K">K是指令类型</typeparam>
/// <typeparam name="M">M是参数类型</typeparam>
/// <typeparam name="N">M是参数类型</typeparam>
public abstract class SqlEx<T, K, M,N> : ISqlEx<T, K, M,N> {
/// <summary>
/// 出错的重试次数 0表示不重试
/// </summary>
public int errorTryAgainCount {
get;
protected set;
}
/// <summary>
/// 出错重试时间增量 单位毫秒 0表示以固定时间间隔重试
/// </summary>
public int errorAgainTimeInc {
get;
protected set;
}
/// <summary>
/// 执行出错 第一次多少秒后进行重试
/// </summary>
public int errorAgainTime {
get;
protected set;
}
/// <summary>
/// 链接池
/// </summary>
public abstract IConnectionPool<T> connPool { get; }
/// <summary>
/// 给存储过程添加参数
/// </summary>
/// <param name="spp">存储过程命令</param>
/// <param name="paramName">参数名</param>
/// <param name="value">参数值</param>
/// <param name="type">参数类型</param>
/// <param name="pd">参数种类</param>
public abstract void AddParam(IProdureParameter<K> spp, string paramName, object value, M type, ParameterDirection pd = ParameterDirection.Input);
/// <summary>
/// 开始执行存储过程
/// </summary>
/// <param name="dbbase">数据库名称</param>
/// <param name="procedure">存储过程名称</param>
/// <returns>存储过程指令</returns>
public abstract IProdureParameter<K> BeginProcedure(string dbbase, string procedure);
/// <summary>
/// 执行一个事务
/// </summary>
/// <param name="dbbase">数据库名称</param>
/// <returns>存储过程指令</returns>
public abstract IProdureParameter<K> BeginTransaction(string dbbase);
/// <summary>
/// 执行cmd
/// </summary>
/// <param name="cmd">数据库指令</param>
/// <param name="dbname">数据库名称</param>
/// <param name="ds">结果集</param>
/// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
/// <returns>受影响的行数</returns>
public abstract int Execute(K cmd,string dbname, DataSet ds = null,int againCount = -1);
/// <summary>
/// 执行sql语句
/// </summary>
/// <param name="dbbase">数据库名称</param>
/// <param name="sql">sql语句</param>
/// <param name="sqlparams">sql的额外参数</param>
/// <param name="ds">查询的结果集</param>
/// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
/// <returns>受影响的行数</returns>
public abstract int ExecuteSql(string dbbase, string sql, IEnumerable<N> sqlparams = null, DataSet ds = null,int againCount = -1);
/// <summary>
/// 获取一个连接
/// </summary>
/// <param name="dbbase">数据库名称</param>
/// <returns>返回链接</returns>
public abstract T GetConnection(string dbbase);
/// <summary>
/// 执行一个普通的查询
/// </summary>
/// <param name="dbbase">数据库名称</param>
/// <param name="table">数据库表名</param>
/// <param name="column">查询的列</param>
/// <param name="where">查询条件</param>
/// <param name="count">查询的行数</param>
/// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
/// <param name="sqlparams">Sql参数</param>
/// <returns>查询的结果集</returns>
public abstract DataTable Select(string dbbase, string table, string[] column = null, string where = null, int count = 0,int againCount = -1, IEnumerable<N> sqlparams = null);
/// <summary>
/// 提交存储过程
/// </summary>
/// <param name="spp">存储过程命令</param>
/// <param name="ds">查询的结果集</param>
/// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
/// <returns>执行存储过程所有参数</returns>
public abstract Dictionary<string, object> SubProcedure(IProdureParameter<K> spp, DataSet ds = null,int againCount = -1);
/// <summary>
/// 提交一个事务
/// </summary>
/// <param name="spp">存储过程指令</param>
/// <returns>是否执行成功</returns>
public abstract bool SubTransaction(IProdureParameter<K> spp);
/// <summary>
/// 为事务添加sql语句
/// </summary>
/// <param name="spp">存储过程指令</param>
/// <param name="sql">sql语句</param>
/// <param name="sqlparams">额外参数</param>
public abstract int TransactionAddSql(IProdureParameter<K> spp, string sql, List<ISqlAloneParameter<M>> sqlparams = null);
/// <summary>
/// 回滚事务
/// </summary>
/// <param name="spp"></param>
public abstract void RollbackTransaction(IProdureParameter<K> spp);
#region
/// <summary>
/// 异步提交存储过程
/// </summary>
public abstract Task<Dictionary<string, object>> SubProcedureAsync(IProdureParameter<K> spp, DataSet ds = null, int againCount = -1);
/// <summary>
/// 异步执行sql语句
/// </summary>
public abstract Task<int> ExecuteSqlAsync(string dbbase, string sql, IEnumerable<N> sqlparams = null, DataSet ds = null, int againCount = -1);
/// <summary>
/// 异步执行一个普通的查询
/// </summary>
public abstract Task<DataTable> SelectAsync(string dbbase, string table, string[] column = null, string where = null, int count = 0, int againCount = -1, IEnumerable<N> sqlparams = null);
/// <summary>
/// 异步执行cmd
/// </summary>
public abstract Task<int> ExecuteAsync(K cmd, string dbname, DataSet ds = null, int againCount = -1);
#endregion
}
}

138
MrWu/DB/SqlParameterData.cs Normal file
View File

@ -0,0 +1,138 @@
/*
* 作者:吴隆健
* 日期: 2019-04-07
* 时间: 20:05
*
*/
#if MMSQL
using System;
using System.Data;
using System.Data.SqlClient;
namespace MrWu.DB
{
/// <summary>
/// 存储过程查询键
/// </summary>
public class SqlProcedureParameter : IProdureParameter<SqlCommand>
{
SqlCommand _sqlcommand;
/// <summary>
/// 查询键
/// </summary>
public SqlCommand command
{
get => _sqlcommand;
}
private string _dbName;
/// <summary>
/// 数据库名称
/// </summary>
public string dbName
{
get => _dbName;
}
/// <summary>
/// 错误信息
/// </summary>
public Exception exception { get; set; }
/// <summary>
/// 是否报错
/// </summary>
public bool isException
{
get { return exception != null; }
}
private SqlProcedureParameter()
{
}
internal SqlProcedureParameter(SqlCommand sqlcommand, string dbName)
{
this._sqlcommand = sqlcommand;
this._dbName = dbName;
}
/// <summary>
/// 释放
/// </summary>
public void Dispose()
{
if (_sqlcommand != null)
{
_sqlcommand.Dispose();
_sqlcommand = null;
}
}
}
/// <summary>
/// 单独设置参数
/// </summary>
public class SqlAloneParameter : ISqlAloneParameter<SqlDbType>
{
string _paramname;
/// <summary>
/// 参数名称
/// </summary>
public string paramname
{
get => _paramname;
}
object _paramvalue;
/// <summary>
/// 参数值
/// </summary>
public object paramvalue
{
get => _paramvalue;
set => _paramvalue = value;
}
SqlDbType _type;
/// <summary>
/// 参数类型
/// </summary>
public SqlDbType type => _type;
int _valueLength;
/// <summary>
/// 参数长度
/// </summary>
public int valueLength => _valueLength;
/// <summary>
/// sql语句单独设置参数
/// </summary>
/// <param name="paramname">参数名称</param>
/// <param name="paramvalue">参数值</param>
/// <param name="valuelength">参数值的长度</param>
/// <param name="type">参数类型</param>
public SqlAloneParameter(string paramname, object paramvalue, int valuelength = 0,
SqlDbType type = SqlDbType.Binary)
{
this._paramname = paramname;
this._paramvalue = paramvalue;
this._valueLength = valuelength;
this._type = type;
}
/// <summary>
/// Direction
/// </summary>
public ParameterDirection Direction { get; set; }
}
}
#endif

48
MrWu/DB/SqlTimer.cs Normal file
View File

@ -0,0 +1,48 @@
/********************************
*
* 作者:吴隆健
* 创建时间: 2019-06-06 16:34:39
*
********************************/
using System;
namespace MrWu.DB {
/// <summary>
/// 数据库定时器
/// </summary>
public class SqlTimer {
/// <summary>
/// 时间间隔单位秒
/// </summary>
public int interval;
/// <summary>
/// 下次运行的时间点
/// </summary>
public long runTime;
/// <summary>
/// 是否运行中
/// </summary>
public bool isRuning {
get;
internal set;
}
/// <summary>
/// 启动定时器
/// </summary>
public void Start() {
}
/// <summary>
/// 停止定时器
/// </summary>
public void Stop() {
}
}
}