MySqlParameter_防注入参数配置

本文详细介绍了在C#中使用MySqlParameter进行数据库操作时如何防止SQL注入,包括MySqlParameter的构造函数、参数传入方式以及ParameterDirection参数方向的使用。通过示例展示了Input、Output、InputOutput和ReturnValue四种模式的配置与应用,强调了在MySQL存储过程中的注意事项。

目录

一、前提准备

二、MySqlParameter 构造函数使用

三、MySqlParameter 参数传入

四、ParameterDirection 参数方向的使用

1、 ParameterDirection.Input输入模式

2、 ParameterDirection.Output输出模式

3、 ParameterDirection.InputOutput输入和输出模式

4、 ParameterDirection.ReturnValue返回模式


涉及知识点:MySqlParamete -- MySQL的存储过程 -- MySQL的function

一、前提准备

1、配置App.config文件  -- 若文件未找到,则 Ctrl+Shift+A --> 添加 " 应用程序配置文件 " 

	<connectionStrings>
		<add name="connStr"
		     connectionString="server=localhost;database=mysql_student;uid=root;pwd=123456"
			 providerName="MySql.Data.MySqlClient"/>
	</connectionStrings>

2、导入Nuget包 

3、引入using

using MySql.Data.MySqlClient;
using System;
using System.Configuration;
using System.Data;

4、创建MySQL 数据表 

create table tb_student_information
(
    id int,
    name varchar(10),
    no int
);
insert into tb_student_information
values (1,'小白',20),
       (2,'小红',30),
       (3,'小兰',35);

二、MySqlParameter 构造函数使用

需要配置的参数:

MySqlParameter.ParameterName = "@Name"  ; //参数名称

MySqlParameter.Value = "小白";        //参数值 

MySqlParameter.MySqlDbTyoe = MySqlDbType.VarChar;        //参数类型

MySqlParameter.Size = 10;  //参数占10个字节 

MySqlParameter.Direction = ParameterDirection.Input; //默认输入状态

以下是MySqlParameter的五种构造方法:

    internal class Program
    {
        static void Main(string[] args)
        {
            //param1.Direction 默认输入模式
            //1.不带参数
            MySqlParameter param1 = new MySqlParameter();
            param1.ParameterName = "@Name";  //参数名称
            param1.Value = "小白";    //参数的值
            param1.MySqlDbType = MySqlDbType.VarChar;  //参数类型
            param1.Size = 10; //10个字节
            param1.Direction = System.Data.ParameterDirection.ReturnValue;
            //2.参数 值
            MySqlParameter param2 = new MySqlParameter("@Name", "小白");
            param2.MySqlDbType = MySqlDbType.VarChar;
            param2.Size = 10;
            //3.参数 类型
            MySqlParameter param3 = new MySqlParameter("@Name", MySqlDbType.VarChar);
            param3.Value = "小白";
            param3.Size = 10;
            //4.参数 类型 大小
            MySqlParameter param4 = new MySqlParameter("@Name", MySqlDbType.VarChar, 10);
            param4.Value = "小白";
            //5.参数 类型 大小 源列名(对应DataTable中的列名)
            MySqlParameter param5 = new MySqlParameter("@Name", MySqlDbType.VarChar, 10, "UName");

            Console.WriteLine("Hello World!");
        }
    }

三、MySqlParameter 参数传入

cmd.Parameters.Add();//添加单个

cmd.Parameters.AddWithValue(); //添加单个(推荐)

cmd.Parameters.AddRange(); //添加多个

以下是参数添加的4中方法:

 internal class Program
    {
        static void Main(string[] args)
        {
            //获取外部文件字符串
            string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;

            string sql = "select * from tb_student_information where name = @name";
            using (MySqlConnection connect = new MySqlConnection(connStr))
            {
                MySqlCommand cmd = new MySqlCommand(sql, connect);
                //1.普通传参数(单个)
                MySqlParameter param = new MySqlParameter("@name", "小白");
                cmd.Parameters.Add(param);
                //2.普通传参数(单个)
                cmd.Parameters.Add(new MySqlParameter("@name", "小白"));
                //3.快捷传参数(单个)(推荐)
                cmd.Parameters.AddWithValue("@name", "小白");
                //4.多个参数传入
                MySqlParameter[] parames = {
                    new MySqlParameter("@name","小白")
                };
                cmd.Parameters.AddRange(parames);
            }
            Console.WriteLine("Hello World!");
        }
    }

四、ParameterDirection 参数方向的使用

参数:

ParameterDirection.Input     -- 是默认的模式,应用于任何场合

ParameterDirection.Output  -- 应用于数据的"存储过程",  --- 获取输出的值

ParameterDirection. InputOutput  -- 应用于数据的"存储过程",   --- 值可以输入也可输出

ParameterDirection.ReturnValue -- 在SQL Sever 的"存储过程可用",但MySQL的"存储过程"不可以,只可以使用MySQL的function, ---- 获取返回值

应用“存储过程”时,需额外配置:

        cmd.CommandType = CommandType.StoredProcedure; //命令类型:存储过程

        param.Direction = ParameterDirection.InputOutput;    //参数方向

1、 ParameterDirection.Input输入模式

修改前数据库数据:

  C#对MySQL的操作: -- C#代码

internal class Program
    {
        static void Main(string[] args)
        {
            //获取外部文件字符串
            string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;

            string sql = "select * from tb_student_information where name = @name";

            using (MySqlConnection connect = new MySqlConnection(connStr))
            {
                MySqlCommand cmd = new MySqlCommand(sql, connect);

                MySqlParameter param = new MySqlParameter("@name", MySqlDbType.VarChar, 10);
                param.Value = "小白";
                param.Direction = ParameterDirection.Input;  //参数方向传入

                cmd.Parameters.Add(param);

                connect.Open();
                object obj = cmd.ExecuteScalar();
                connect.Close();

                Console.WriteLine(obj.ToString());
            }
            Console.WriteLine("Hello World!");
        }
    }

 结果: 

2、 ParameterDirection.Output输出模式

修改前数据库数据:

 MySQL数据库中的数据过程配置:  -- MySQL 代码

delimiter $$
create procedure GetName(id int, out name varchar(10))
begin
    select tb_student_information.name into name
    from tb_student_information
    where tb_student_information.id = id;
end $$

 C#对MySQL的操作: -- C#代码

 internal class Program
    {
        static void Main(string[] args)
        {
            //获取外部文件字符串
            string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;

            using (MySqlConnection connect = new MySqlConnection(connStr))
            {
                MySqlCommand cmd = new MySqlCommand("GetName", connect);
                cmd.CommandType = CommandType.StoredProcedure; //命令类型:存储过程

                cmd.Parameters.AddWithValue("id", 2);

                MySqlParameter param = new MySqlParameter("name", MySqlDbType.VarChar, 10);
                param.Direction = ParameterDirection.Output; //参数方向:输出

                cmd.Parameters.Add(param);

                connect.Open();
                cmd.ExecuteScalar();
                connect.Close();

                Console.WriteLine(param.Value.ToString());
            }
            Console.WriteLine("Hello World!");
        }
    }

结果显示:

3、 ParameterDirection.InputOutput输入和输出模式

修改前数据库数据:

 MySQL数据库中的数据过程配置:  -- MySQL 代码

delimiter $$
create procedure GetName1(id int,inout name varchar(10))
begin
    declare sname varchar(10) default 'no';
    select tb_student_information.name into sname
    from tb_student_information
    where tb_student_information.id = id;
    set name = concat(sname,name);  #拼接字符串
end $$

 C#对MySQL的操作: -- C#代码

    internal class Program
    {
        static void Main(string[] args)
        {
            //获取外部文件字符串
            string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;

            using (MySqlConnection connect = new MySqlConnection(connStr))
            {
                MySqlCommand cmd = new MySqlCommand("GetName1", connect);
                cmd.CommandType = CommandType.StoredProcedure; //命令类型:存储过程

                cmd.Parameters.AddWithValue("id", 2);

                MySqlParameter param = new MySqlParameter("name", MySqlDbType.VarChar, 10);
                param.Value = "同学";
                param.Direction = ParameterDirection.InputOutput;

                cmd.Parameters.Add(param);

                connect.Open();
                cmd.ExecuteScalar();
                connect.Close();

                Console.WriteLine(param.Value.ToString());
            }
            Console.WriteLine("Hello World!");
        }
    }

结果显示:

4、 ParameterDirection.ReturnValue返回模式

注要事项: 

        1、SQL sever 的"存储过程" 只可以返回int类型 
        2、MySQL 的"存储过程",没有return,只能用function, 但他可以获取所有类型                      3、(第一次使用function可能会出现)这里创建函数时可能会遇到错误:ERROR 1418 (HY000):
This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled(you* might* want to use the less safe log_bin_trust_function_creators variable)

          解决方式: set global log_bin_trust_function_creators=TRUE;

 修改前数据库数据:

 MySQL数据库中的数据过程配置:  -- MySQL 代码

create function returnId( sid int) returns varchar(10)
begin
declare sname varchar(10);
select tb.name into sname
from tb_student_information as tb
where tb.id = sid;
return sname;
end $$

 C#对MySQL的操作: -- C#代码

    internal class Program
    {
        static void Main(string[] args)
        {
            //获取外部文件字符串
            string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;

            using (MySqlConnection connect = new MySqlConnection(connStr))
            {
                MySqlCommand cmd = new MySqlCommand("returnId", connect);
                cmd.CommandType = CommandType.StoredProcedure; //命令类型:存储过程

                MySqlParameter[] parames = {
                    new MySqlParameter("sid",1),
                    new MySqlParameter("sname",MySqlDbType.VarChar,10)
                };
                parames[1].Direction = ParameterDirection.ReturnValue; //参数方向:返回值

                cmd.Parameters.AddRange(parames);

                connect.Open();
                cmd.ExecuteScalar();
                connect.Close();

                Console.WriteLine(parames[1].Value.ToString());
            }
            Console.WriteLine("Hello World!");
        }
    }

结果显示:


如有错误,烦请批评指正

Imports System.IO Imports MySql.Data.MySqlClient Imports PrnComexcep Imports PrnDatawork Imports PrnDatbasehlp Imports PrnGlbcfg Imports PrnUtlthods Public Class SystemService Implements IDisposable Private _configRepository As SystemConfigRepository Private _authorizationService As AuthorizationService Private _isDisposed As Boolean = False Public Sub New() _configRepository = New SystemConfigRepository() _authorizationService = New AuthorizationService() End Sub Public Async Function GetSystemConfigAsync(configKey As String, currentUserId As Integer) As Task(Of SystemConfigResult) Try Dim hasAccess = Await _authorizationService.CheckOperationPermissionAsync(currentUserId, "system_config_view") If Not hasAccess Then Return New SystemConfigResult(False, Nothing, "没有查看系统配置的权限") End If Dim config = Await _configRepository.GetConfigByKeyAsync(configKey) If config Is Nothing Then Return New SystemConfigResult(False, Nothing, "配置项不存在") End If Return New SystemConfigResult(True, config, "获取系统配置成功") Catch ex As Exception Logger.Error($"获取系统配置失败: {configKey}", ex) Return New SystemConfigResult(False, Nothing, "系统错误,请稍后重试") End Try End Function Public Async Function UpdateSystemConfigAsync(configKey As String, configValue As String, updatedBy As Integer) As Task(Of OperationResult) Try Dim hasAccess = Await _authorizationService.CheckOperationPermissionAsync(updatedBy, "system_config_update") If Not hasAccess Then Return New OperationResult(False, "没有更新系统配置的权限") End If Dim existingConfig = Await _configRepository.GetConfigByKeyAsync(configKey) If existingConfig Is Nothing Then Return New OperationResult(False, "配置项不存在") End If If existingConfig.IsSystem Then Return New OperationResult(False, "系统配置项不允许修改") End If existingConfig.ConfigValue = configValue existingConfig.UpdatedTime = DateTime.Now existingConfig.UpdatedBy = updatedBy Dim success = Await _configRepository.UpdateConfigAsync(existingConfig) If success Then ConfigManager.UpdateConfig(configKey, configValue) Return New OperationResult(True, "系统配置更新成功") Else Return New OperationResult(False, "系统配置更新失败") End If Catch ex As Exception Logger.Error($"更新系统配置失败: {configKey}", ex) Return New OperationResult(False, "系统错误,请稍后重试") End Try End Function Public Async Function GetAllConfigsAsync(currentUserId As Integer) As Task(Of SystemConfigsResult) Try Dim hasAccess = Await _authorizationService.CheckOperationPermissionAsync(currentUserId, "system_config_view") If Not hasAccess Then Return New SystemConfigsResult(False, Nothing, "没有查看系统配置的权限") End If Dim configs = Await _configRepository.GetAllConfigsAsync() Return New SystemConfigsResult(True, configs, "获取系统配置列表成功") Catch ex As Exception Logger.Error("获取系统配置列表失败", ex) Return New SystemConfigsResult(False, Nothing, "系统错误,请稍后重试") End Try End Function Public Async Function GetSystemStatusAsync(currentUserId As Integer) As Task(Of SystemStatusResult) Try Dim hasAccess = Await _authorizationService.CheckOperationPermissionAsync(currentUserId, "system_monitor") If Not hasAccess Then Return New SystemStatusResult(False, Nothing, "没有查看系统状态的权限") End If Dim status As New SystemStatus With { .ServerStartTime = DateTime.Now.AddHours(-2), .DatabaseStatus = Await CheckDatabaseStatusAsync(), .ActiveSessions = Await GetActiveSessionsCountAsync(), .MemoryUsage = GetMemoryUsage(), .CPUUsage = GetCPUUsage(), .DiskSpace = GetDiskSpace() } Return New SystemStatusResult(True, status, "获取系统状态成功") Catch ex As Exception Logger.Error("获取系统状态失败", ex) Return New SystemStatusResult(False, Nothing, "系统错误,请稍后重试") End Try End Function Public Async Function BackupDatabaseAsync(backupPath As String, backupBy As Integer) As Task(Of OperationResult) Try Dim hasAccess = Await _authorizationService.CheckOperationPermissionAsync(backupBy, "system_backup") If Not hasAccess Then Return New OperationResult(False, "没有备份数据库的权限") End If If String.IsNullOrEmpty(backupPath) Then backupPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Backups") End If If Not Directory.Exists(backupPath) Then Directory.CreateDirectory(backupPath) End If Dim backupFile = Path.Combine(backupPath, $"backup_{DateTime.Now:yyyyMMddHHmmss}.sql") Dim success = Await PerformDatabaseBackupAsync(backupFile) If success Then Return New OperationResult(True, $"数据库备份成功: {backupFile}") Else Return New OperationResult(False, "数据库备份失败") End If Catch ex As Exception Logger.Error("数据库备份失败", ex) Return New OperationResult(False, "系统错误,请稍后重试") End Try End Function Public Async Function CleanupOldDataAsync(daysToKeep As Integer, cleanedBy As Integer) As Task(Of OperationResult) Try Dim hasAccess = Await _authorizationService.CheckOperationPermissionAsync(cleanedBy, "system_cleanup") If Not hasAccess Then Return New OperationResult(False, "没有清理数据的权限") End If Dim cutoffDate = DateTime.Now.AddDays(-daysToKeep) Using uow As New UnitOfWork() uow.BeginTransaction() Dim cleanupLogsSql = "DELETE FROM system_operation_log WHERE operation_time < @cutoffDate" Dim cleanupLogsParams = {uow.GetDatabaseHelper().CreateParameter("@cutoffDate", cutoffDate)} Await uow.GetDatabaseHelper().ExecuteNonQueryAsync(cleanupLogsSql, cleanupLogsParams) Dim cleanupSessionsSql = "DELETE FROM user_session WHERE login_time < @cutoffDate AND is_active = 0" Dim cleanupSessionsParams = {uow.GetDatabaseHelper().CreateParameter("@cutoffDate", cutoffDate)} Await uow.GetDatabaseHelper().ExecuteNonQueryAsync(cleanupSessionsSql, cleanupSessionsParams) uow.Commit() End Using Return New OperationResult(True, $"数据清理完成,保留{daysToKeep}天内的数据") Catch ex As Exception Logger.Error("数据清理失败", ex) Return New OperationResult(False, "系统错误,请稍后重试") End Try End Function Private Async Function CheckDatabaseStatusAsync() As Task(Of Boolean) Try Return Await DbContext.Instance.TestConnectionAsync() Catch ex As Exception Return False End Try End Function Private Async Function GetActiveSessionsCountAsync() As Task(Of Integer) Try Using sessionService As New SessionManagementService() Return Await sessionService.GetActiveSessionsCountAsync() End Using Catch ex As Exception Return 0 End Try End Function Private Function GetMemoryUsage() As String Try Dim process = process.GetCurrentProcess() Dim memoryMB = process.WorkingSet64 / 1024 / 1024 Return $"{memoryMB:F2} MB" Catch ex As Exception Return "N/A" End Try End Function Private Function GetCPUUsage() As String Try Return "N/A" Catch ex As Exception Return "N/A" End Try End Function Private Function GetDiskSpace() As String Try Dim drive = New DriveInfo(Path.GetPathRoot(Environment.CurrentDirectory)) Dim freeSpaceGB = drive.AvailableFreeSpace / 1024 / 1024 / 1024 Dim totalSpaceGB = drive.TotalSize / 1024 / 1024 / 1024 Return $"{freeSpaceGB:F1} GB / {totalSpaceGB:F1} GB" Catch ex As Exception Return "N/A" End Try End Function Private Async Function PerformDatabaseBackupAsync(backupFile As String) As Task(Of Boolean) Try Using dbHelper As New DatabaseHelper() Await dbHelper.OpenConnectionAsync() Using cmd As New MySqlCommand() cmd.Connection = dbHelper.Connection cmd.CommandText = "SELECT * FROM sys_user" Using reader As MySqlDataReader = Await cmd.ExecuteReaderAsync() Using writer As New StreamWriter(backupFile) While Await reader.ReadAsync() Dim values As New List(Of String)() For i As Integer = 0 To reader.FieldCount - 1 values.Add(If(reader.IsDBNull(i), "NULL", $"'{reader.GetValue(i).ToString().Replace("'", "''")}'")) Next writer.WriteLine($"INSERT INTO sys_user VALUES ({String.Join(", ", values)});") End While End Using End Using End Using End Using Return True Catch ex As Exception Logger.Error("执行数据库备份失败", ex) Return False End Try End Function Public Sub Dispose() Implements IDisposable.Dispose If Not _isDisposed Then If _configRepository IsNot Nothing Then _configRepository.Dispose() _configRepository = Nothing End If If _authorizationService IsNot Nothing Then _authorizationService.Dispose() _authorizationService = Nothing End If _isDisposed = True End If End Sub End Class Public Class SystemConfigResult Public Property Success As Boolean Public Property Config As SystemConfig Public Property Message As String Public Sub New(success As Boolean, config As SystemConfig, message As String) Me.Success = success Me.Config = config Me.Message = message End Sub End Class Public Class SystemConfigsResult Public Property Success As Boolean Public Property Configs As List(Of SystemConfig) Public Property Message As String Public Sub New(success As Boolean, configs As List(Of SystemConfig), message As String) Me.Success = success Me.Configs = configs Me.Message = message End Sub End Class Public Class SystemStatusResult Public Property Success As Boolean Public Property Status As SystemStatus Public Property Message As String Public Sub New(success As Boolean, status As SystemStatus, message As String) Me.Success = success Me.Status = status Me.Message = message End Sub End Class Public Class SystemConfig Public Property ConfigId As Integer Public Property ConfigKey As String Public Property ConfigValue As String Public Property ConfigType As String Public Property Description As String Public Property IsSystem As Boolean Public Property CreatedTime As DateTime Public Property UpdatedTime As DateTime End Class Public Class SystemStatus Public Property ServerStartTime As DateTime Public Property DatabaseStatus As Boolean Public Property ActiveSessions As Integer Public Property MemoryUsage As String Public Property CPUUsage As String Public Property DiskSpace As String End Class Public Class SystemConfigRepository Implements IDisposable Private _dbHelper As DatabaseHelper Public Sub New() _dbHelper = DbContext.Instance.GetConnection() End Sub Public Async Function GetConfigByKeyAsync(configKey As String) As Task(Of SystemConfig) Try Dim sql As String = "SELECT * FROM system_config WHERE config_key = @configKey" Dim parameters As MySqlParameter() = { _dbHelper.CreateParameter("@configKey", configKey) } Dim dataTable As DataTable = Await _dbHelper.GetDataTableAsync(sql, parameters) If dataTable.Rows.Count > 0 Then Return DataRowToConfig(dataTable.Rows(0)) Else Return Nothing End If Catch ex As Exception Logger.Error($"获取系统配置失败: {configKey}", ex) Throw New DatabaseException($"获取系统配置失败", 0, $"SELECT * FROM system_config WHERE config_key = '{configKey}'", ex) End Try End Function Public Async Function GetAllConfigsAsync() As Task(Of List(Of SystemConfig)) Try Dim sql As String = "SELECT * FROM system_config ORDER BY config_key" Dim dataTable As DataTable = Await _dbHelper.GetDataTableAsync(sql) Return DataTableToConfigList(dataTable) Catch ex As Exception Logger.Error("获取所有系统配置失败", ex) Throw New DatabaseException("获取所有系统配置失败", 0, "SELECT * FROM system_config", ex) End Try End Function Public Async Function UpdateConfigAsync(config As SystemConfig) As Task(Of Boolean) Try Dim sql As String = "UPDATE system_config SET config_value = @configValue, updated_time = @updatedTime, updated_by = @updatedBy WHERE config_id = @configId" Dim parameters As MySqlParameter() = { _dbHelper.CreateParameter("@configValue", config.ConfigValue), _dbHelper.CreateParameter("@updatedTime", config.UpdatedTime), _dbHelper.CreateParameter("@updatedBy", config.UpdatedBy), _dbHelper.CreateParameter("@configId", config.ConfigId) } Dim result As Integer = Await _dbHelper.ExecuteNonQueryAsync(sql, parameters) Return result > 0 Catch ex As Exception Logger.Error($"更新系统配置失败: {config.ConfigKey}", ex) Throw New DatabaseException($"更新系统配置失败", 0, "UPDATE", ex) End Try End Function Private Function DataRowToConfig(row As DataRow) As SystemConfig Return New SystemConfig With { .ConfigId = Convert.ToInt32(row("config_id")), .ConfigKey = row("config_key").ToString(), .ConfigValue = row("config_value").ToString(), .ConfigType = row("config_type").ToString(), .Description = If(row.IsNull("description"), String.Empty, row("description").ToString()), .IsSystem = Convert.ToBoolean(row("is_system")), .CreatedTime = Convert.ToDateTime(row("created_time")), .UpdatedTime = Convert.ToDateTime(row("updated_time")) } End Function Private Function DataTableToConfigList(dataTable As DataTable) As List(Of SystemConfig) Dim configs As New List(Of SystemConfig)() For Each row As DataRow In dataTable.Rows configs.Add(DataRowToConfig(row)) Next Return configs End Function Public Sub Dispose() Implements IDisposable.Dispose If _dbHelper IsNot Nothing Then DbContext.Instance.ReturnConnection(_dbHelper) _dbHelper = Nothing End If End Sub End Class 检查错误
最新发布
11-03
using System; using System.Collections.Generic; using System.Configuration; using System.Data; using System.Data.Common; using System.Data.SqlClient; using System.Linq; using Oracle.ManagedDataAccess.Client; using MySql.Data.MySqlClient; namespace StorehouseServer.Helper { /// <summary> /// 数据库Helper /// </summary> public class DatabaseHelper : IDisposable { private DbConnection _connection; private readonly DatabaseType _databaseType; private string _connectionString; private const int MaxRetryCount = 3; private const int RetryDelayMs = 1000; public enum DatabaseType { SqlServer, Oracle, MySql } /// <summary> /// 构造函数 /// </summary> /// <param name="databaseType">数据库类型</param> /// <param name="connectionStringName">配置文件中连接字符串的名称</param> /// <exception cref="ArgumentNullException">当connectionStringName为null或空时抛出</exception> /// <exception cref="ConfigurationErrorsException">当连接字符串配置不存在时抛出</exception> public DatabaseHelper(DatabaseType databaseType, string connectionStringName) { if (string.IsNullOrWhiteSpace(connectionStringName)) throw new ArgumentNullException(nameof(connectionStringName), "Connection string name cannot be null or empty."); _databaseType = databaseType; var connectionSettings = ConfigurationManager.ConnectionStrings[connectionStringName]; if (connectionSettings == null) throw new ConfigurationErrorsException($"Connection string '{connectionStringName}' not found in configuration."); // 从配置文件中获取加密的连接字符串并解密 var encryptedConnString = connectionSettings.ConnectionString; if (string.IsNullOrWhiteSpace(encryptedConnString)) throw new ConfigurationErrorsException($"Connection string '{connectionStringName}' is empty."); _connectionString = StringEncryptor.Decrypt(encryptedConnString); // 确保连接字符串包含连接池设置 EnsureConnectionPoolSettings(); } /// <summary> /// 确保连接字符串包含连接池设置 /// </summary> private void EnsureConnectionPoolSettings() { // 根据不同数据库类型添加连接池优化参数 switch (_databaseType) { case DatabaseType.SqlServer: var sqlBuilder = new SqlConnectionStringBuilder(_connectionString) { Pooling = true, MaxPoolSize = 100, MinPoolSize = 5, ConnectTimeout = 15 }; _connectionString = sqlBuilder.ToString(); break; case DatabaseType.Oracle: var oracleBuilder = new OracleConnectionStringBuilder(_connectionString) { Pooling = true, MaxPoolSize = 100, MinPoolSize = 5, ConnectionTimeout = 15 }; _connectionString = oracleBuilder.ToString(); break; case DatabaseType.MySql: var mysqlBuilder = new MySqlConnectionStringBuilder(_connectionString) { Pooling = true, MaximumPoolSize = 100, MinimumPoolSize = 5, ConnectionTimeout = 15 }; _connectionString = mysqlBuilder.ToString(); break; } } /// <summary> /// 初始化数据库连接 /// </summary> private DbConnection InitializeConnection() { DbConnection connection; switch (_databaseType) { case DatabaseType.SqlServer: connection = new SqlConnection(_connectionString); break; case DatabaseType.Oracle: connection = new OracleConnection(_connectionString); break; case DatabaseType.MySql: connection = new MySqlConnection(_connectionString); break; default: throw new ArgumentException("Unsupported database type"); } // 设置连接超时和重试策略 connection.ConnectionString = _connectionString; return connection; } /// <summary> /// 获取数据库连接(带重试机制) /// </summary> public DbConnection GetConnection() { if (_connection == null) { _connection = InitializeConnection(); } // 检查连接状态,必要时重新连接 if (_connection.State != ConnectionState.Open) { int retryCount = 0; while (retryCount < MaxRetryCount) { try { _connection.Open(); return _connection; } catch (DbException) { retryCount++; if (retryCount >= MaxRetryCount) throw; System.Threading.Thread.Sleep(RetryDelayMs); // 尝试重新初始化连接 try { _connection.Dispose(); } catch { } _connection = InitializeConnection(); } } } return _connection; } /// <summary> /// 创建新的数据库连接(不自动打开) /// </summary> public DbConnection CreateConnection() { DbConnection connection; switch (_databaseType) { case DatabaseType.SqlServer: connection = new SqlConnection(_connectionString); break; case DatabaseType.Oracle: connection = new OracleConnection(_connectionString); break; case DatabaseType.MySql: connection = new MySqlConnection(_connectionString); break; default: throw new ArgumentException("Unsupported database type"); } return connection; } /// <summary> /// 执行非查询SQL语句 /// </summary> /// <param name="sql">SQL语句</param> /// <param name="parameters">参数</param> /// <returns>受影响的行数</returns> /// <exception cref="ArgumentNullException">当sql为null或空时抛出</exception> public int ExecuteNonQuery(string sql, params DbParameter[] parameters) { if (string.IsNullOrWhiteSpace(sql)) throw new ArgumentNullException(nameof(sql), "SQL statement cannot be null or empty."); using (var connection = GetConnection()) { using (DbCommand command = CreateCommand(connection, sql, parameters)) { return command.ExecuteNonQuery(); } } } /// <summary> /// 执行查询并返回DataTable /// </summary> /// <param name="sql">SQL语句</param> /// <param name="parameters">参数</param> /// <returns>DataTable结果</returns> /// <exception cref="ArgumentNullException">当sql为null或空时抛出</exception> public DataTable ExecuteDataTable(string sql, params DbParameter[] parameters) { if (string.IsNullOrWhiteSpace(sql)) throw new ArgumentNullException(nameof(sql), "SQL statement cannot be null or empty."); using (var connection = GetConnection()) { using (DbCommand command = CreateCommand(connection, sql, parameters)) { using (DbDataAdapter adapter = CreateDataAdapter(command)) { DataTable dt = new DataTable(); adapter.Fill(dt); return dt; } } } } /// <summary> /// 执行查询并返回DataTable(支持事务) /// </summary> public DataTable ExecuteDataTable(string sql, DbTransaction transaction, params DbParameter[] parameters) { if (string.IsNullOrWhiteSpace(sql)) throw new ArgumentNullException(nameof(sql)); using (DbCommand command = CreateCommand(transaction.Connection, sql, parameters)) { command.Transaction = transaction; using (DbDataAdapter adapter = CreateDataAdapter(command)) { DataTable dt = new DataTable(); adapter.Fill(dt); return dt; } } } /// <summary> /// 执行查询并返回第一行第一列的值 /// </summary> /// <param name="sql">SQL语句</param> /// <param name="parameters">参数</param> /// <returns>结果</returns> /// <exception cref="ArgumentNullException">当sql为null或空时抛出</exception> public object ExecuteScalar(string sql, params DbParameter[] parameters) { if (string.IsNullOrWhiteSpace(sql)) throw new ArgumentNullException(nameof(sql), "SQL statement cannot be null or empty."); using (var connection = GetConnection()) { using (DbCommand command = CreateCommand(connection, sql, parameters)) { return command.ExecuteScalar(); } } } /// <summary> /// 执行存储过程 /// </summary> /// <param name="procedureName">存储过程名称</param> /// <param name="parameters">参数</param> /// <returns>DataTable结果</returns> /// <exception cref="ArgumentNullException">当procedureName为null或空时抛出</exception> public DataTable ExecuteStoredProcedure(string procedureName, params DbParameter[] parameters) { if (string.IsNullOrWhiteSpace(procedureName)) throw new ArgumentNullException(nameof(procedureName), "Procedure name cannot be null or empty."); using (var connection = GetConnection()) { using (DbCommand command = connection.CreateCommand()) { command.CommandText = procedureName; command.CommandType = CommandType.StoredProcedure; if (parameters != null && parameters.Length > 0) { foreach (var param in parameters) { if (param == null) continue; command.Parameters.Add(param); } } using (DbDataAdapter adapter = CreateDataAdapter(command)) { DataTable dt = new DataTable(); adapter.Fill(dt); return dt; } } } } /// <summary> /// 创建数据库命令 /// </summary> private DbCommand CreateCommand(DbConnection connection, string sql, params DbParameter[] parameters) { DbCommand command = connection.CreateCommand(); command.CommandText = sql; command.CommandType = CommandType.Text; if (parameters != null && parameters.Length > 0) { foreach (var param in parameters) { if (param == null) continue; command.Parameters.Add(param); } } return command; } /// <summary> /// 创建数据适配器 /// </summary> private DbDataAdapter CreateDataAdapter(DbCommand command) { switch (_databaseType) { case DatabaseType.SqlServer: return new SqlDataAdapter((SqlCommand)command); case DatabaseType.Oracle: return new OracleDataAdapter((OracleCommand)command); case DatabaseType.MySql: return new MySqlDataAdapter((MySqlCommand)command); default: throw new ArgumentException("Unsupported database type"); } } /// <summary> /// 创建参数 /// </summary> /// <param name="name">参数名</param> /// <param name="value">参数值</param> /// <param name="dbType">参数类型</param> /// <param name="direction">参数方向</param> /// <returns>DbParameter实例</returns> /// <exception cref="ArgumentNullException">当name为null或空时抛出</exception> public DbParameter CreateParameter(string name, object value, DbType dbType, ParameterDirection direction = ParameterDirection.Input) { if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullException(nameof(name), "Parameter name cannot be null or empty."); DbParameter parameter; switch (_databaseType) { case DatabaseType.SqlServer: parameter = new SqlParameter(name, value ?? DBNull.Value); break; case DatabaseType.Oracle: parameter = new OracleParameter(name, value ?? DBNull.Value); break; case DatabaseType.MySql: parameter = new MySqlParameter(name, value ?? DBNull.Value); break; default: throw new ArgumentException("Unsupported database type"); } parameter.DbType = dbType; parameter.Direction = direction; return parameter; } /// <summary> /// 开始事务 /// </summary> /// <returns>DbTransaction实例</returns> public DbTransaction BeginTransaction() { var connection = GetConnection(); return connection.BeginTransaction(); } /// <summary> /// 执行事务操作 /// </summary> /// <param name="action">要执行的事务操作</param> /// <exception cref="ArgumentNullException">当action为null时抛出</exception> public void ExecuteInTransaction(Action<DbTransaction> action) { if (action == null) throw new ArgumentNullException(nameof(action), "Action cannot be null."); using (var connection = GetConnection()) { using (var transaction = connection.BeginTransaction()) { try { action(transaction); transaction.Commit(); } catch { try { transaction.Rollback(); } catch (Exception ex) { // 记录日志或处理回滚异常 throw new Exception("Transaction rollback failed.", ex); } throw; } } } } /// <summary> /// 释放资源 /// </summary> public void Dispose() { if (_connection != null) { try { if (_connection.State != ConnectionState.Closed) { _connection.Close(); } _connection.Dispose(); } catch { // 忽略释放过程中的异常 } finally { _connection = null; } } } } }
08-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值