using System.Data;
using System.Data.Common;
using Milimoe.FunGame.Core.Api.Transmittal;
using Milimoe.FunGame.Core.Library.Constant;
using Milimoe.FunGame.Core.Model;
using Milimoe.FunGame.Server.Models;
using MySql.Data.MySqlClient;
namespace Milimoe.FunGame.Server.Services.DataUtility
{
public class MySQLHelper : SQLHelper
{
///
/// FunGame 类型
///
public override FunGameInfo.FunGame FunGameType { get; } = FunGameInfo.FunGame.FunGame_Server;
///
/// 使用的数据库类型
///
public override SQLMode Mode { get; } = SQLMode.MySQL;
///
/// SQL 脚本
///
public override string Script { get; set; } = "";
///
/// 命令类型
///
public override CommandType CommandType { get; set; } = CommandType.Text;
///
/// 数据库事务
///
public override DbTransaction? Transaction => _transaction;
///
/// 执行结果
///
public override SQLResult Result => _result;
///
/// SQL 服务器信息
///
public override SQLServerInfo ServerInfo => _serverInfo ?? SQLServerInfo.Create();
///
/// 上一次执行命令影响的行数
///
public override int AffectedRows => _affectedRows;
///
/// 上一次执行的命令是 Insert 时,返回的自增 ID,大于 0 有效
///
public override long LastInsertId => _lastInsertId;
///
/// 上一次执行命令的查询结果集
///
public override DataSet DataSet => _dataSet;
///
/// SQL 语句参数
///
public override Dictionary Parameters { get; } = [];
private readonly string _connectionString = "";
private MySqlConnection? _connection;
private MySqlTransaction? _transaction;
private DataSet _dataSet = new();
private SQLResult _result = SQLResult.NotFound;
private readonly SQLServerInfo? _serverInfo;
private int _affectedRows = 0;
private long _lastInsertId = 0;
public MySQLHelper(string script = "", CommandType type = CommandType.Text)
{
Script = script;
CommandType = type;
_connectionString = ConnectProperties.GetConnectPropertiesForMySQL();
string[] strings = _connectionString.Split(";");
if (strings.Length > 1 && strings[0].Length > 14 && strings[1].Length > 8)
{
string ip = strings[0][14..];
string port = strings[1][8..];
_serverInfo = SQLServerInfo.Create(ip: ip, port: port);
}
}
///
/// 打开数据库连接
///
private void OpenConnection()
{
_connection ??= new MySqlConnection(_connectionString);
if (_connection.State != ConnectionState.Open)
{
_connection.Open();
}
}
///
/// 关闭数据库连接
///
public override void Close()
{
_transaction?.Dispose();
_transaction = null;
if (_connection?.State != ConnectionState.Closed)
{
_connection?.Close();
}
_connection?.Dispose();
_connection = null;
}
///
/// 执行现有命令()
///
///
public override int Execute()
{
return Execute(Script);
}
///
/// 执行一个指定的命令
///
///
///
public override int Execute(string script)
{
bool localTransaction = _transaction == null;
try
{
if (localTransaction)
{
NewTransaction();
}
OpenConnection();
Script = script;
ServerHelper.WriteLine("SQLQuery -> " + script, InvokeMessageType.Api);
using MySqlCommand command = new(script, _connection);
command.CommandType = CommandType;
foreach (KeyValuePair param in Parameters)
{
command.Parameters.AddWithValue(param.Key, param.Value);
}
if (_transaction != null) command.Transaction = _transaction;
ReSet();
_affectedRows = command.ExecuteNonQuery();
if (_affectedRows > 0)
{
_result = SQLResult.Success;
if (script.Contains(Core.Library.SQLScript.Constant.Command_Insert, StringComparison.OrdinalIgnoreCase))
{
_lastInsertId = command.LastInsertedId;
if (_lastInsertId < 0) _lastInsertId = 0;
}
}
else _result = SQLResult.Fail;
if (localTransaction) Commit();
}
catch (Exception e)
{
if (localTransaction) Rollback();
_result = SQLResult.SQLError;
ServerHelper.Error(e);
}
finally
{
if (localTransaction) Close();
if (ClearParametersAfterExecute) Parameters.Clear();
}
return AffectedRows;
}
///
/// 异步执行现有命令()
///
///
public override async Task ExecuteAsync()
{
return await ExecuteAsync(Script);
}
///
/// 异步执行一个指定的命令
///
///
///
public override async Task ExecuteAsync(string script)
{
bool localTransaction = _transaction == null;
try
{
if (localTransaction)
{
NewTransaction();
}
OpenConnection();
Script = script;
ServerHelper.WriteLine("SQLQuery -> " + script, InvokeMessageType.Api);
using MySqlCommand command = new(script, _connection);
command.CommandType = CommandType;
foreach (KeyValuePair param in Parameters)
{
command.Parameters.AddWithValue(param.Key, param.Value);
}
if (_transaction != null) command.Transaction = _transaction;
ReSet();
_affectedRows = await command.ExecuteNonQueryAsync();
if (_affectedRows > 0)
{
_result = SQLResult.Success;
if (script.Contains(Core.Library.SQLScript.Constant.Command_Insert, StringComparison.OrdinalIgnoreCase))
{
_lastInsertId = command.LastInsertedId;
if (_lastInsertId < 0) _lastInsertId = 0;
}
}
else _result = SQLResult.Fail;
if (localTransaction) Commit();
}
catch (Exception e)
{
if (localTransaction) Rollback();
_result = SQLResult.SQLError;
ServerHelper.Error(e);
}
finally
{
if (localTransaction) Close();
if (ClearParametersAfterExecute) Parameters.Clear();
}
return AffectedRows;
}
///
/// 执行现有命令()查询 DataSet
///
///
public override DataSet ExecuteDataSet()
{
return ExecuteDataSet(Script);
}
///
/// 执行指定的命令查询 DataSet
///
///
///
public override DataSet ExecuteDataSet(string script)
{
bool localTransaction = _transaction == null;
try
{
if (localTransaction)
{
NewTransaction();
}
OpenConnection();
Script = script;
ServerHelper.WriteLine("SQLQuery -> " + script, InvokeMessageType.Api);
using MySqlCommand command = new(script, _connection)
{
CommandType = CommandType
};
foreach (KeyValuePair param in Parameters)
{
command.Parameters.AddWithValue(param.Key, param.Value);
}
if (_transaction != null) command.Transaction = _transaction;
ReSet();
MySqlDataAdapter adapter = new()
{
SelectCommand = command
};
_dataSet = new();
_affectedRows = adapter.Fill(_dataSet);
if (localTransaction) Commit();
_result = _dataSet.Tables.Cast().Any(table => table.Rows.Count > 0) ? SQLResult.Success : SQLResult.NotFound;
}
catch (Exception e)
{
if (localTransaction) Rollback();
_result = SQLResult.SQLError;
ServerHelper.Error(e);
}
finally
{
if (localTransaction) Close();
if (ClearParametersAfterExecute) Parameters.Clear();
}
return _dataSet;
}
///
/// 异步执行现有命令()查询 DataSet
///
///
public override async Task ExecuteDataSetAsync()
{
return await ExecuteDataSetAsync(Script);
}
///
/// 异步执行指定的命令查询 DataSet
///
///
///
public override async Task ExecuteDataSetAsync(string script)
{
bool localTransaction = _transaction == null;
try
{
if (localTransaction)
{
NewTransaction();
}
OpenConnection();
Script = script;
ServerHelper.WriteLine("SQLQuery -> " + script, InvokeMessageType.Api);
using MySqlCommand command = new(script, _connection)
{
CommandType = CommandType
};
foreach (KeyValuePair param in Parameters)
{
command.Parameters.AddWithValue(param.Key, param.Value);
}
if (_transaction != null) command.Transaction = _transaction;
ReSet();
MySqlDataAdapter adapter = new()
{
SelectCommand = command
};
_dataSet = new();
_affectedRows = await adapter.FillAsync(_dataSet);
if (localTransaction) Commit();
_result = _dataSet.Tables.Cast().Any(table => table.Rows.Count > 0) ? SQLResult.Success : SQLResult.NotFound;
}
catch (Exception e)
{
if (localTransaction) Rollback();
_result = SQLResult.SQLError;
ServerHelper.Error(e);
}
finally
{
if (localTransaction) Close();
if (ClearParametersAfterExecute) Parameters.Clear();
}
return _dataSet;
}
///
/// 创建一个SQL事务
///
public override void NewTransaction()
{
OpenConnection();
if (_connection != null)
{
_transaction = _connection.BeginTransaction();
}
}
///
/// 提交事务
///
public override void Commit()
{
try
{
_transaction?.Commit();
_result = SQLResult.Success;
}
catch (Exception e)
{
_result = SQLResult.SQLError;
ServerHelper.Error(e);
}
finally
{
_transaction = null;
}
}
///
/// 回滚事务
///
public override void Rollback()
{
try
{
_transaction?.Rollback();
_result = SQLResult.SQLError;
}
catch (Exception e)
{
_result = SQLResult.SQLError;
ServerHelper.Error(e);
}
finally
{
_transaction = null;
}
}
///
/// 检查数据库是否存在
///
///
public override bool DatabaseExists()
{
try
{
ExecuteDataSet(Core.Library.SQLScript.Common.Configs.Select_GetConfig(this, "Initialization"));
return Success;
}
catch (Exception e)
{
ServerHelper.Error(e);
_result = SQLResult.SQLError;
return false;
}
finally
{
Close();
}
}
private bool _isDisposed = false;
///
/// 资源清理
///
private void Dispose(bool disposing)
{
if (!_isDisposed)
{
if (disposing)
{
_transaction?.Dispose();
_transaction = null;
_connection?.Close();
_connection?.Dispose();
_connection = null;
}
}
_isDisposed = true;
}
public override void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void ReSet()
{
_result = SQLResult.NotFound;
_affectedRows = 0;
_lastInsertId = 0;
DataSet.Clear();
}
}
}