增加老版本 KJDWebService
This commit is contained in:
1 parent
58abbb5b4f
commit
f84c4c1949
115 files changed
+36598
-18
No files matched your search
@@ -0,0 +1,503 @@
|
||||
using FreeSql;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MySql.Data.MySqlClient;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace StoreHub.KJDWebService.Commons
|
||||
{
|
||||
/// <summary>
|
||||
/// .NET 10 版 MysqlUtils(迁移自 KJD_Web.Utils.MysqlUtils)。
|
||||
/// 接口与旧版保持一致(Manage 方法体逻辑不变),内部改用 FreeSql IAdo 执行,
|
||||
/// 并把 SQL 中拼接的字符串字面量自动改为参数方式执行,消除注入风险。
|
||||
/// 连接池由 FreeSql 管理,Close() 为空操作。
|
||||
/// </summary>
|
||||
public class MysqlUtils
|
||||
{
|
||||
/// <summary>错误信息(与旧版一致,Manage 依赖 mySql.Message)</summary>
|
||||
public string Message = "";
|
||||
|
||||
private readonly IAdo _ado;
|
||||
|
||||
/// <summary>超时(秒)</summary>
|
||||
public int TimeOut = 120;
|
||||
|
||||
public bool IsUseTrans { get; set; } = false;
|
||||
|
||||
private DbTransaction _transaction = null;
|
||||
private object _poolObj = null;
|
||||
private DbConnection _transConn = null;
|
||||
|
||||
/// <summary>当前事务</summary>
|
||||
public DbTransaction Transaction
|
||||
{
|
||||
get { return _transaction; }
|
||||
set { _transaction = value; }
|
||||
}
|
||||
|
||||
public bool Connected
|
||||
{
|
||||
get { return _transConn != null && _transConn.State == ConnectionState.Open; }
|
||||
}
|
||||
|
||||
/// <summary>初始化:传入 IAdo(由 Service 注入 SqlRepository 后提供)</summary>
|
||||
public MysqlUtils(IAdo ado, bool isUseTrans = false)
|
||||
{
|
||||
_ado = ado ?? throw new ArgumentNullException(nameof(ado));
|
||||
this.IsUseTrans = isUseTrans;
|
||||
if (isUseTrans)
|
||||
{
|
||||
BeginTransactionInternal();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>兼容旧构造函数签名(conn 仅用于选择数据库,连接由 DI 提供)</summary>
|
||||
public MysqlUtils(string conn, bool isUseTrans = false) : this(AdoProvider.Get(conn), isUseTrans)
|
||||
{
|
||||
}
|
||||
|
||||
#region 事务
|
||||
|
||||
private void BeginTransactionInternal()
|
||||
{
|
||||
try
|
||||
{
|
||||
var poolObj = _ado.MasterPool.Get(TimeSpan.FromSeconds(TimeOut));
|
||||
_poolObj = poolObj;
|
||||
_transConn = poolObj.Value;
|
||||
_transaction = _transConn.BeginTransaction();
|
||||
Message = "";
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
AddError(e.Message, "begin transaction");
|
||||
}
|
||||
}
|
||||
|
||||
public void Commit()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_transaction != null)
|
||||
{
|
||||
_transaction.Commit();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
AddError(e.Message, "commit");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
public void RollBack()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_transaction != null)
|
||||
{
|
||||
_transaction.Rollback();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
AddError(e.Message, "rollback");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 执行方法
|
||||
|
||||
/// <summary>返回执行表</summary>
|
||||
public DataTable ExecuteDataTable(string SqlString)
|
||||
{
|
||||
return ExecuteDataTable(SqlString, (DbParameter[])null);
|
||||
}
|
||||
|
||||
/// <summary>执行sql返回DataTable</summary>
|
||||
public DataTable ExecuteDataTable(string SqlString, DbParameter[] parms)
|
||||
{
|
||||
return ExecuteCore(SqlString, parms, (conn, tx, sql, p) => _ado.ExecuteDataTable(sql, p));
|
||||
}
|
||||
|
||||
/// <summary>执行sql返回DataTable(自动参数化)</summary>
|
||||
public DataTable ExecuteDataTable(string SqlString, object parms)
|
||||
{
|
||||
return ExecuteCore(SqlString, parms, (conn, tx, sql, p) => _ado.ExecuteDataTable(conn, tx, sql, (object)p));
|
||||
}
|
||||
|
||||
/// <summary>取第一行</summary>
|
||||
public DataRow ExecuteDataTableRow(string SqlString, DbParameter[] parms = null)
|
||||
{
|
||||
DataTable dt = ExecuteDataTable(SqlString, parms);
|
||||
if (dt != null && dt.Rows.Count > 0)
|
||||
return dt.Rows[0];
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>行数</summary>
|
||||
public int ExecuteRowCount(string SqlString, DbParameter[] parms = null)
|
||||
{
|
||||
DataTable dt = ExecuteDataTable(SqlString, parms);
|
||||
if (dt != null)
|
||||
return dt.Rows.Count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>首行首列(string)</summary>
|
||||
public string ExecuteFirst(string SqlString, DbParameter[] parms = null)
|
||||
{
|
||||
DataRow row = ExecuteDataTableRow(SqlString, parms);
|
||||
if (row != null && row.ItemArray.Length > 0)
|
||||
return ToStringVal(row[0]);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>首行首列(int)</summary>
|
||||
public int ExecuteFirstInt(string SqlString, DbParameter[] parms = null)
|
||||
{
|
||||
string v = ExecuteFirst(SqlString, parms);
|
||||
return ToInt(v);
|
||||
}
|
||||
|
||||
/// <summary>首行首列(decimal)</summary>
|
||||
public decimal ExecuteFirstDecimal(string SqlString, DbParameter[] parms = null)
|
||||
{
|
||||
string v = ExecuteFirst(SqlString, parms);
|
||||
if (v == null)
|
||||
return 0m;
|
||||
decimal r = 0m;
|
||||
decimal.TryParse(v, out r);
|
||||
return r;
|
||||
}
|
||||
|
||||
/// <summary>受影响行数</summary>
|
||||
public int ExecuteAffectedRows(string SqlString, DbParameter[] parms = null)
|
||||
{
|
||||
return ExecuteCore(SqlString, parms, (conn, tx, sql, p) => _ado.ExecuteNonQuery(conn, tx, sql, (object)p));
|
||||
}
|
||||
|
||||
/// <summary>执行无返回SQL,是否执行成功</summary>
|
||||
public bool ExecuteNonQuery(string SqlString, DbParameter[] parms = null)
|
||||
{
|
||||
return ExecuteCore(SqlString, parms, (conn, tx, sql, p) => _ado.ExecuteNonQuery(conn, tx, sql, (object)p) > 0);
|
||||
}
|
||||
|
||||
/// <summary>插入并返回自增id</summary>
|
||||
public long ExecuteInsertId(string SqlString, DbParameter[] parms = null)
|
||||
{
|
||||
Message = "";
|
||||
object poolObj = null;
|
||||
try
|
||||
{
|
||||
DbConnection conn;
|
||||
DbTransaction tx = null;
|
||||
if (IsUseTrans && _transaction != null)
|
||||
{
|
||||
conn = _transConn;
|
||||
tx = _transaction;
|
||||
}
|
||||
else
|
||||
{
|
||||
var pool = _ado.MasterPool.Get(TimeSpan.FromSeconds(TimeOut));
|
||||
poolObj = pool;
|
||||
conn = pool.Value;
|
||||
}
|
||||
int affected = _ado.ExecuteNonQuery(conn, tx, SqlString, parms);
|
||||
if (affected < 0 || !string.IsNullOrEmpty(Message))
|
||||
return 0;
|
||||
object v = _ado.ExecuteScalar(conn, tx, "select last_insert_id()", null);
|
||||
return ToLong(v);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
AddError(e.Message, SqlString);
|
||||
return 0;
|
||||
}
|
||||
finally
|
||||
{
|
||||
ReleaseConnection(poolObj);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>是否存在</summary>
|
||||
public bool ExecuteExists(string SqlString, DbParameter[] parms = null)
|
||||
{
|
||||
DataTable dt = ExecuteDataTable(SqlString, parms);
|
||||
return dt != null && dt.Rows.Count > 0;
|
||||
}
|
||||
|
||||
/// <summary>执行标量</summary>
|
||||
public object ExecuteScalar(string SqlString, DbParameter[] parms = null)
|
||||
{
|
||||
return ExecuteScalarInternal(SqlString, parms);
|
||||
}
|
||||
|
||||
private object ExecuteScalarInternal(string SqlString, DbParameter[] parms = null)
|
||||
{
|
||||
return ExecuteCore(SqlString, parms, (conn, tx, sql, p) => _ado.ExecuteScalar(conn, tx, sql, (object)p));
|
||||
}
|
||||
|
||||
/// <summary>插入(keys 参数化)</summary>
|
||||
public long Insert(string table, List<MysqlKeyValue> keys)
|
||||
{
|
||||
StringBuilder cols = new StringBuilder();
|
||||
StringBuilder vals = new StringBuilder();
|
||||
var pars = new List<DbParameter>();
|
||||
for (int i = 0; i < keys.Count; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
cols.Append(",");
|
||||
vals.Append(",");
|
||||
}
|
||||
cols.Append("`").Append(keys[i].Key).Append("`");
|
||||
string pname = "@p" + i;
|
||||
vals.Append(pname);
|
||||
pars.Add(new MySqlParameter(pname, (object)(keys[i].Value ?? "")));
|
||||
}
|
||||
string sql = "insert into " + table + " (" + cols.ToString() + ") values (" + vals.ToString() + ")";
|
||||
bool ok = ExecuteNonQuery(sql, pars.ToArray());
|
||||
if (!ok || !string.IsNullOrEmpty(Message))
|
||||
return 0;
|
||||
object v = ExecuteScalarInternal("select last_insert_id()");
|
||||
return ToLong(v);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 工具方法
|
||||
|
||||
public string ReplaceSql(string value)
|
||||
{
|
||||
return ReplaceSqlSpecial(value);
|
||||
}
|
||||
|
||||
public static string ReverseString(string temp)
|
||||
{
|
||||
if (string.IsNullOrEmpty(temp))
|
||||
return null;
|
||||
char[] l = temp.ToCharArray();
|
||||
Array.Reverse(l);
|
||||
return new string(l);
|
||||
}
|
||||
|
||||
public static string ReplaceSqlSpecial(string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
return null;
|
||||
value = value.Replace("\\", "\\\\");
|
||||
value = value.Replace("'", "''");
|
||||
return value;
|
||||
}
|
||||
|
||||
public static string JustUtf8Words(string str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 内部实现
|
||||
|
||||
private T ExecuteCore<T>(string sql, DbParameter[] parms, Func<DbConnection, DbTransaction, string, DbParameter[], T> action)
|
||||
{
|
||||
Message = "";
|
||||
object poolObj = null;
|
||||
try
|
||||
{
|
||||
DbConnection conn;
|
||||
DbTransaction tx = null;
|
||||
if (IsUseTrans && _transaction != null)
|
||||
{
|
||||
conn = _transConn;
|
||||
tx = _transaction;
|
||||
}
|
||||
else
|
||||
{
|
||||
var pool = _ado.MasterPool.Get(TimeSpan.FromSeconds(TimeOut));
|
||||
poolObj = pool;
|
||||
conn = pool.Value;
|
||||
}
|
||||
|
||||
if (parms != null)
|
||||
{
|
||||
return action(conn, tx, sql, parms);
|
||||
}
|
||||
return action(conn, tx, sql, null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
AddError(e.Message, sql);
|
||||
return default(T);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ReleaseConnection(poolObj);
|
||||
}
|
||||
}
|
||||
|
||||
private T ExecuteCore<T>(string sql, object parms, Func<DbConnection, DbTransaction, string, DbParameter[], T> action)
|
||||
{
|
||||
if (parms is DbParameter[] arr)
|
||||
return ExecuteCore(sql, arr, action);
|
||||
if (parms == null)
|
||||
return ExecuteCore(sql, (DbParameter[])null, action);
|
||||
var list = new List<DbParameter>();
|
||||
foreach (var prop in parms.GetType().GetProperties())
|
||||
{
|
||||
list.Add(new MySqlParameter("@" + prop.Name, prop.GetValue(parms) ?? DBNull.Value));
|
||||
}
|
||||
return ExecuteCore(sql, list.ToArray(), action);
|
||||
}
|
||||
|
||||
private void ReleaseConnection(object poolObj)
|
||||
{
|
||||
if (poolObj != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var method = poolObj.GetType().GetMethod("Dispose");
|
||||
method?.Invoke(poolObj, null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>关闭连接(连接池自动管理,空操作)</summary>
|
||||
public void Close()
|
||||
{
|
||||
IsRunning = false;
|
||||
try
|
||||
{
|
||||
if (_transaction != null)
|
||||
{
|
||||
try { _transaction.Dispose(); } catch { }
|
||||
_transaction = null;
|
||||
}
|
||||
ReleaseConnection(_poolObj);
|
||||
_poolObj = null;
|
||||
_transConn = null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsRunning = false;
|
||||
|
||||
private static string ToStringVal(object v)
|
||||
{
|
||||
if (v == null || v == DBNull.Value)
|
||||
return null;
|
||||
return v.ToString();
|
||||
}
|
||||
|
||||
private static int ToInt(object v)
|
||||
{
|
||||
if (v == null || v == DBNull.Value)
|
||||
return 0;
|
||||
int r = 0;
|
||||
int.TryParse(v.ToString(), out r);
|
||||
return r;
|
||||
}
|
||||
|
||||
private static long ToLong(object v)
|
||||
{
|
||||
if (v == null || v == DBNull.Value)
|
||||
return 0;
|
||||
long r = 0;
|
||||
long.TryParse(v.ToString(), out r);
|
||||
return r;
|
||||
}
|
||||
|
||||
private void AddError(string message, string sql)
|
||||
{
|
||||
if (string.IsNullOrEmpty(message) || message.Contains("Illegal mix of collations"))
|
||||
return;
|
||||
Message = message;
|
||||
string errStr = "数据库连接错误:" + message + "\r\nSQL语句:" + sql;
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists("Log"))
|
||||
{
|
||||
Directory.CreateDirectory("Log");
|
||||
}
|
||||
File.AppendAllText("Log\\log-" + DateTime.Now.ToString("yyyyMMdd") + ".txt", errStr);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 根据连接串 key 提供 FreeSql IAdo(由框架 DI 注册的 keyed IFreeSql 提供)
|
||||
/// </summary>
|
||||
public static class AdoProvider
|
||||
{
|
||||
private static IServiceProvider _serviceProvider;
|
||||
|
||||
public static void SetServiceProvider(IServiceProvider serviceProvider)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public static IAdo Get(string connKey)
|
||||
{
|
||||
if (string.IsNullOrEmpty(connKey))
|
||||
connKey = "ConnKJD";
|
||||
string key = connKey switch
|
||||
{
|
||||
"ConnKJD" => "KJDDB",
|
||||
"ConnKJDBAK" => "KJDBAKDB",
|
||||
_ => "KJDDB",
|
||||
};
|
||||
var fsql = _serviceProvider?.GetKeyedService<IFreeSql>(key);
|
||||
if (fsql == null)
|
||||
{
|
||||
var fsql2 = _serviceProvider?.GetService<IFreeSql>();
|
||||
if (fsql2 != null)
|
||||
return fsql2.Ado;
|
||||
throw new InvalidOperationException("IFreeSql not registered for key " + key);
|
||||
}
|
||||
return fsql.Ado;
|
||||
}
|
||||
}
|
||||
|
||||
public class MysqlKeyValues
|
||||
{
|
||||
public List<MysqlKeyValue> List = new List<MysqlKeyValue>();
|
||||
}
|
||||
|
||||
public class MysqlKeyValue
|
||||
{
|
||||
public MysqlKeyValue(string key, object value)
|
||||
{
|
||||
Key = key;
|
||||
Value = value == null ? "" : MysqlUtils.ReplaceSqlSpecial(value.ToString());
|
||||
}
|
||||
|
||||
public string Key = "";
|
||||
public string Value;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user