一、概述
MySQL
类是一个用于封装与 MySQL 数据库交互操作的工具类,支持链式调用风格来实现增删改查等常见数据库操作。它提供了一系列方便的方法,允许用户轻松地进行数据库连接、数据查询、插入、更新和删除等操作,同时还支持事务处理和批量插入功能。
二、类的主要属性和方法
2.1 属性
server
:数据库服务器地址。port
:数据库服务器端口号。database
:要连接的数据库名称。username
:登录数据库的用户名。password
:登录数据库的密码。tableName
:当前操作的表名。columns
:用于存储查询时指定的列名列表。whereClause
:存储查询的 WHERE 条件语句。orderByColumn
:用于指定排序的列名。orderByDescending
:表示排序是否为降序,默认是升序(false
)。limit
:用于指定查询结果的限制数量。connection
:数据库连接对象。
2.2 方法
2.2.1 构造函数
public MySQL(string server, int port)
- 功能:接收数据库服务器地址和端口号,初始化相关属性并尝试建立数据库连接。
- 参数:
server
:数据库服务器地址。port
:数据库服务器端口号。
2.2.2 链式方法
2.2.2.1 数据库连接信息设置
Database(string database)
:设置要连接的数据库名称。返回当前MySQL
类实例,方便继续链式调用。User(string username)
:设置登录用户名。返回当前MySQL
类实例,方便继续链式调用。Password(string password)
:设置登录密码。返回当前MySQL
类实例,方便继续链式调用。
2.2.2.2 操作表设置
Table(string tableName)
:设置当前操作表名。返回当前MySQL
类实例,方便继续链式调用。
2.2.2.3 列选择设置
Col(string column)
:添加单个列名到列名列表,用于指定查询时选择的列。返回当前MySQL
类实例,方便继续链式调用。Col(List<string> columns)
:添加多个列名到列名列表,用于指定查询时选择的列。返回当前MySQL
类实例,方便继续链式调用。- 示例:
MySQL mysql = new MySQL("localhost", 3306) .Database("testdb") .User("root") .Password("password") .Table("users") .Col("Name") .Col("Age"); DataTable result = mysql.All();
上述代码中,通过
Col
方法指定了查询users
表时只选择Name
和Age
两列。
2.2.2.4 查询条件设置
Where(string whereClause)
:设置查询的 WHERE 条件语句。返回当前MySQL
类实例,方便继续链式调用。ID(int id)
:设置 WHERE 条件为根据 ID 字段来筛选某一条特定记录,相当于Where("ID = " + id)
。返回当前MySQL
类实例,方便继续链式调用。- 示例:
MySQL mysql = new MySQL("localhost", 3306) .Database("testdb") .User("root") .Password("password") .Table("users") .Where("Age > 20"); DataTable result = mysql.All();
上述代码中,通过
Where
方法设置查询条件,只查询users
表中Age
大于 20 的记录。
MySQL mysql = new MySQL("localhost", 3306)
.Database("testdb")
.User("root")
.Password("password")
.Table("users")
.ID(1);
DataRow user = mysql.One();
上述代码中,通过 ID
方法设置查询条件,只查询 users
表中 ID
为 1 的记录。
2.2.2.5 排序设置
By(string orderByColumn, bool descending = false)
:设置排序字段以及是否降序排序(默认为升序)。返回当前MySQL
类实例,方便继续链式调用。- 示例:
MySQL mysql = new MySQL("localhost", 3306) .Database("testdb") .User("root") .Password("password") .Table("users") .By("Age", true); DataTable result = mysql.All();
上述代码中,通过
By
方法设置按照Age
字段降序排序查询users
表的记录。
2.2.2.6 分页设置
Lim(int limit)
:设置查询结果限制数量,可用于实现分页功能。返回当前MySQL
类实例,方便继续链式调用。- 示例:
// 假设每页显示 10 条记录,查询第 2 页的数据 int pageSize = 10; int pageNumber = 2; int offset = (pageNumber - 1) * pageSize; MySQL mysql = new MySQL("localhost", 3306) .Database("testdb") .User("root") .Password("password") .Table("users") .Where("Age > 20") .Lim(pageSize); // 在实际应用中,可能需要在 SQL 生成部分添加 OFFSET 支持,当前代码可扩展修改实现 // 这里仅展示 Lim 方法用于限制每页数量 DataTable result = mysql.All();
上述代码中,通过
Lim
方法设置每页显示 10 条记录,结合页码计算偏移量,可实现分页查询。
2.2.3 查询方法
All()
:执行查询并返回包含所有符合条件的数据的DataTable
对象,用于获取多条查询结果。AllAsync(CancellationToken cancellationToken = default)
:异步版本的All()
方法。One()
:执行查询并返回符合条件的第一条数据(如果有),以DataRow
对象形式返回,用于获取单条查询结果。
2.2.4 数据操作方法
Insert(Dictionary<string, object> values)
:插入数据,接收一个字典,键为要插入的列名,值为对应列要插入的值,执行插入操作后返回受影响的行数。Update(Dictionary<string, object> values)
:更新数据,接收一个字典,键为要更新的列名,值为对应列要更新的值,执行更新操作后返回受影响的行数。Delete()
:删除数据,根据之前设置的 WHERE 条件(如果有)构建 DELETE 语句,执行删除操作后返回受影响的行数。
2.2.5 其他方法
Close()
:关闭数据库连接。判断连接对象是否存在且处于打开状态,如果是则关闭连接,释放数据库连接资源。Query(string sql)
:执行自定义数据库指令,接收一个自定义的 SQL 语句字符串作为参数,打开数据库连接后执行该语句,返回受影响的行数。使用时要注意防止 SQL 注入,可使用参数化查询。ExecuteTransaction(Action<MySqlTransaction> action)
:事务处理方法,接收一个包含事务操作的委托。在事务中执行一系列数据库操作,如果其中一个操作失败,整个事务将回滚。BulkInsert(List<Dictionary<string, object>> dataList)
:批量插入方法,接收一个包含多个字典的列表,每个字典表示一条要插入的数据,返回受影响的行数。
三、使用示例
3.1 初始化数据库连接
using XL.Database;
// 创建 MySQL 实例
MySQL mysql = new MySQL("localhost", 3306)
.Database("testdb")
.User("root")
.Password("password");
3.2 查询数据
3.2.1 查询所有数据
// 设置要操作的表
mysql.Table("users");
// 查询所有用户数据
DataTable allUsers = mysql.All();
foreach (DataRow row in allUsers.Rows)
{
Console.WriteLine($"ID: {row["ID"]}, Name: {row["Name"]}");
}
3.2.2 异步查询所有数据
// 异步查询所有用户数据
var task = mysql.AllAsync();
task.Wait();
DataTable allUsersAsync = task.Result;
foreach (DataRow row in allUsersAsync.Rows)
{
Console.WriteLine($"ID: {row["ID"]}, Name: {row["Name"]}");
}
3.2.3 查询单条数据
// 根据 ID 查询单条用户数据
DataRow user = mysql.ID(1).One();
if (user != null)
{
Console.WriteLine($"ID: {user["ID"]}, Name: {user["Name"]}");
}
3.3 插入数据
// 插入一条新用户数据
Dictionary<string, object> newUser = new Dictionary<string, object>
{
{ "Name", "John Doe" },
{ "Age", 30 }
};
int rowsAffected = mysql.Insert(newUser);
Console.WriteLine($"插入 {rowsAffected} 条记录");
3.4 更新数据
// 更新用户数据
Dictionary<string, object> updatedUser = new Dictionary<string, object>
{
{ "Age", 31 }
};
int updatedRows = mysql.ID(1).Update(updatedUser);
Console.WriteLine($"更新 {updatedRows} 条记录");
3.5 删除数据
// 删除用户数据
int deletedRows = mysql.ID(1).Delete();
Console.WriteLine($"删除 {deletedRows} 条记录");
3.6 执行自定义 SQL 语句
// 执行自定义 SQL 语句
string sql = "CREATE TABLE IF NOT EXISTS new_table (ID INT PRIMARY KEY AUTO_INCREMENT, Name VARCHAR(50))";
int result = mysql.Query(sql);
Console.WriteLine($"执行自定义 SQL 语句,受影响的行数: {result}");
3.7 事务处理
// 事务处理示例
mysql.ExecuteTransaction(transaction =>
{
try
{
// 插入一条数据
Dictionary<string, object> data1 = new Dictionary<string, object>
{
{ "Name", "Transaction User 1" },
{ "Age", 25 }
};
using (MySqlCommand command1 = new MySqlCommand($"INSERT INTO users (Name, Age) VALUES (@Name, @Age)", mysql.GetConnection(), transaction))
{
command1.Parameters.AddWithValue("@Name", data1["Name"]);
command1.Parameters.AddWithValue("@Age", data1["Age"]);
command1.ExecuteNonQuery();
}
// 更新一条数据
Dictionary<string, object> data2 = new Dictionary<string, object>
{
{ "Age", 26 }
};
using (MySqlCommand command2 = new MySqlCommand($"UPDATE users SET Age = @Age WHERE Name = 'Transaction User 1'", mysql.GetConnection(), transaction))
{
command2.Parameters.AddWithValue("@Age", data2["Age"]);
command2.ExecuteNonQuery();
}
}
catch (Exception ex)
{
throw new Exception("事务执行出错", ex);
}
});
3.8 批量插入
// 批量插入数据
List<Dictionary<string, object>> dataList = new List<Dictionary<string, object>>
{
new Dictionary<string, object>
{
{ "Name", "Bulk User 1" },
{ "Age", 20 }
},
new Dictionary<string, object>
{
{ "Name", "Bulk User 2" },
{ "Age", 21 }
}
};
int bulkInsertRows = mysql.BulkInsert(dataList);
Console.WriteLine($"批量插入 {bulkInsertRows} 条记录");
3.9 关闭数据库连接
// 关闭数据库连接
mysql.Close();
四、注意事项
- 在使用链式调用时,要确保正确设置数据库连接信息(如数据库名、用户名、密码)和操作表名。
- 在执行 SQL 语句时,要注意防止 SQL 注入,可使用参数化查询。
- 在使用事务处理时,要确保事务内的操作正确,避免因异常导致事务回滚。
- 在使用批量插入时,要确保传入的数据列表不为空。
五、代码
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MySql.Data.MySqlClient;
namespace XL.Database
{
// MySQL类用于封装与MySQL数据库的交互操作,支持链式调用风格来实现增删改查等常见数据库操作
public class MySQL
{
// 数据库服务器地址
private string server;
// 数据库服务器端口号
private int port;
// 要连接的数据库名称
private string database;
// 登录数据库的用户名
private string username;
// 登录数据库的密码
private string password;
// 当前操作的表名
private string tableName;
// 用于存储查询时指定的列名列表,初始为空,后续通过Col方法添加列名
private List<string> columns = [];
// 存储查询的WHERE条件语句,初始为空,通过Where方法设置
private string whereClause;
// 用于指定排序的列名,初始为空,通过By方法设置
private string orderByColumn;
// 表示排序是否为降序,默认是升序(false),通过By方法设置
private bool orderByDescending;
// 用于指定查询结果的限制数量,初始为0,通过Lim方法设置
private int limit;
// 用于保存数据库连接对象,初始为null,在实例化时尝试创建长连接
private MySqlConnection connection;
// 连接池管理
private static readonly ConcurrentDictionary<string, string> connectionStrings = new();
// 构造函数,接收数据库服务器地址和端口号,初始化相关属性并尝试建立数据库连接
public MySQL(string server, int port)
{
this.server = server;
this.port = port;
this.database = "";
this.username = "";
this.password = "";
this.connection = null;
// 生成连接池key
string poolKey = $"{server}:{port}";
// 存储连接字符串
string connectionString = $"server={server};port={port};database={database};user={username};password={password};Connection Timeout=15;pooling=true;min pool size=1;max pool size=100;";
connectionStrings[poolKey] = connectionString;
try
{
// 创建新连接
connection = new MySqlConnection(connectionString);
connection.Open();
}
catch (MySqlException ex)
{
// 记录日志
LogError($"数据库连接创建失败: {ex.Message}");
throw new DatabaseConnectionException("数据库连接失败", ex);
}
}
// 自定义数据库连接异常
public class DatabaseConnectionException : Exception
{
public DatabaseConnectionException(string message, Exception innerException)
: base(message, innerException) { }
}
// 自定义数据库操作异常
public class DatabaseOperationException : Exception
{
public DatabaseOperationException(string message, Exception innerException)
: base(message, innerException) { }
}
// 设置要连接的数据库名称的链式方法,返回当前MySQL类实例,方便继续链式调用
public MySQL Database(string database)
{
this.database = database;
return this;
}
// 设置登录用户名的链式方法,返回当前MySQL类实例,方便继续链式调用
public MySQL User(string username)
{
this.username = username;
return this;
}
// 设置登录密码的链式方法,返回当前MySQL类实例,方便继续链式调用
public MySQL Password(string password)
{
this.password = password;
return this;
}
// 设置当前操作表名的链式方法,返回当前MySQL类实例,方便继续链式调用
public MySQL Table(string tableName)
{
this.tableName = tableName;
return this;
}
// 添加单个列名到列名列表的链式方法,用于指定查询时选择的列,返回当前MySQL类实例,方便继续链式调用
public MySQL Col(string column)
{
columns.Add(column);
return this;
}
// 添加多个列名到列名列表的链式方法,用于指定查询时选择的列,返回当前MySQL类实例,方便继续链式调用
public MySQL Col(List<string> columns)
{
this.columns.AddRange(columns);
return this;
}
// 设置查询的WHERE条件语句的链式方法,返回当前MySQL类实例,方便继续链式调用
public MySQL Where(string whereClause)
{
this.whereClause = whereClause;
return this;
}
// 设置排序字段以及是否降序排序(默认为升序)的链式方法,返回当前MySQL类实例,方便继续链式调用
public MySQL By(string orderByColumn, bool descending = false)
{
this.orderByColumn = orderByColumn;
this.orderByDescending = descending;
return this;
}
// 设置查询结果限制数量的链式方法,返回当前MySQL类实例,方便继续链式调用
public MySQL Lim(int limit)
{
this.limit = limit;
return this;
}
// 一种快捷方式,用于设置WHERE条件为根据ID字段来筛选某一条特定记录,返回当前MySQL类实例,方便继续链式调用
public MySQL ID(int id)
{
whereClause = $"ID={id}";
return this;
}
// 获取数据库连接对象的方法,直接返回已创建的连接对象(在构造函数中已创建长连接)
private MySqlConnection GetConnection()
{
return connection;
}
// 根据列名列表构建查询语句中的列选择子句,如果列列表为空则返回 * 表示选择所有列
private string GetColumnsClause()
{
if (columns.Count == 0)
{
return "*";
}
return string.Join(",", columns);
}
// 根据设置的排序字段和排序顺序(升序或降序)构建ORDER BY子句,用于查询语句中
private string GetOrderByClause()
{
if (orderByColumn != null)
{
string orderBy = orderByColumn;
if (orderByDescending)
{
orderBy += " DESC";
}
return $"ORDER BY {orderBy}";
}
return "";
}
// 根据设置的限制数量构建LIMIT子句,用于查询语句中
private string GetLimitClause()
{
if (limit > 0)
{
return $"LIMIT {limit}";
}
return "";
}
// 综合前面的列选择、WHERE条件、排序和限制等信息,构建完整的SELECT查询语句
private string GetSelectQuery()
{
string columnsClause = GetColumnsClause();
string where = whereClause != null ? $"WHERE {whereClause}" : "";
string orderBy = GetOrderByClause();
string limit = GetLimitClause();
return $"SELECT {columnsClause} FROM {tableName} {where} {orderBy} {limit}";
}
// 执行查询并返回包含所有符合条件的数据的DataTable对象,用于获取多条查询结果
public DataTable All()
{
try
{
using (MySqlConnection connection = GetConnection())
{
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
string query = GetSelectQuery();
using (MySqlCommand command = new MySqlCommand(query, connection))
{
using (MySqlDataAdapter adapter = new MySqlDataAdapter(command))
{
DataTable dataTable = new DataTable();
adapter.Fill(dataTable);
return dataTable;
}
}
}
}
catch (MySqlException ex)
{
LogError($"查询数据失败(All方法): {ex.Message}");
throw new DatabaseOperationException("查询数据失败", ex);
}
}
// 异步版本
public async Task<DataTable> AllAsync(CancellationToken cancellationToken = default)
{
try
{
using (MySqlConnection connection = GetConnection())
{
if (connection.State != ConnectionState.Open)
{
await connection.OpenAsync(cancellationToken);
}
string query = GetSelectQuery();
using (MySqlCommand command = new MySqlCommand(query, connection))
{
using (MySqlDataAdapter adapter = new MySqlDataAdapter(command))
{
DataTable dataTable = new DataTable();
await Task.Run(() => adapter.Fill(dataTable), cancellationToken);
return dataTable;
}
}
}
}
catch (MySqlException ex)
{
LogError($"异步查询数据失败(AllAsync方法): {ex.Message}");
throw new DatabaseOperationException("异步查询数据失败", ex);
}
}
// 执行查询并返回符合条件的第一条数据(如果有),以DataRow对象形式返回,用于获取单条查询结果
public DataRow One()
{
try
{
using (MySqlConnection connection = GetConnection())
{
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
string query = GetSelectQuery() + " LIMIT 1";
using (MySqlCommand command = new MySqlCommand(query, connection))
{
using (MySqlDataReader reader = command.ExecuteReader())
{
if (reader.Read())
{
DataTable dataTable = new DataTable();
DataTable schemaTable = reader.GetSchemaTable();
DataRow row = dataTable.NewRow();
for (int i = 0; i < schemaTable.Rows.Count; i++)
{
row[schemaTable.Rows[i]["ColumnName"].ToString()??string.Empty] = reader[schemaTable.Rows[i]["ColumnName"].ToString()];
}
return row;
}
return default;
}
}
}
}
catch (MySqlException ex)
{
LogError($"查询数据失败(One方法): {ex.Message}");
throw new DatabaseOperationException("查询数据失败", ex);
}
}
// 插入数据方法,接收一个字典,键为要插入的列名,值为对应列要插入的值,执行插入操作后返回受影响的行数
public int Insert(Dictionary<string, object> values)
{
try
{
using (MySqlConnection connection = GetConnection())
{
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
string columnsStr = string.Join(",", values.Keys);
string valuesStr = string.Join(",", values.Keys.Select(key => $"@{key}"));
string query = $"INSERT INTO {tableName} ({columnsStr}) VALUES ({valuesStr})";
using (MySqlCommand command = new MySqlCommand(query, connection))
{
foreach (var pair in values)
{
command.Parameters.AddWithValue($"@{pair.Key}", pair.Value);
}
return command.ExecuteNonQuery();
}
}
}
catch (MySqlException ex)
{
LogError($"插入数据失败: {ex.Message}");
throw new DatabaseOperationException("插入数据失败", ex);
}
}
// 更新数据方法,接收一个字典,键为要更新的列名,值为对应列要更新的值,执行更新操作后返回受影响的行数
public int Update(Dictionary<string, object> values)
{
try
{
using (MySqlConnection connection = GetConnection())
{
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
List<string> setClauses = new List<string>();
foreach (var pair in values)
{
setClauses.Add($"{pair.Key}=@{pair.Key}");
}
string setClause = string.Join(",", setClauses);
string query = $"UPDATE {tableName} SET {setClause} {whereClause}";
using (MySqlCommand command = new MySqlCommand(query, connection))
{
foreach (var pair in values)
{
command.Parameters.AddWithValue($"@{pair.Key}", pair.Value);
}
return command.ExecuteNonQuery();
}
}
}
catch (MySqlException ex)
{
LogError($"更新数据失败: {ex.Message}");
throw new DatabaseOperationException("更新数据失败", ex);
}
}
// 删除数据方法,根据之前设置的WHERE条件(如果有)构建DELETE语句,执行删除操作后返回受影响的行数
public int Delete()
{
try
{
using (MySqlConnection connection = GetConnection())
{
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
string query = $"DELETE FROM {tableName} {whereClause}";
using (MySqlCommand command = new MySqlCommand(query, connection))
{
return command.ExecuteNonQuery();
}
}
}
catch (MySqlException ex)
{
LogError($"删除数据失败: {ex.Message}");
throw new DatabaseOperationException("删除数据失败", ex);
}
}
// 关闭数据库连接方法,判断连接对象是否存在且处于打开状态,如果是则关闭连接,释放数据库连接资源
public void Close()
{
try
{
if (connection != null && connection.State != ConnectionState.Closed)
{
connection.Close();
}
}
catch (MySqlException ex)
{
LogError($"关闭数据库连接失败: {ex.Message}");
throw;
}
}
// 日志记录方法
private void LogError(string message)
{
// 这里可以扩展为写入文件、数据库或发送到日志服务
Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] ERROR: {message}");
}
// 执行自定义数据库指令方法,接收一个自定义的SQL语句字符串作为参数,打开数据库连接后执行该语句,返回受影响的行数
public int Query(string sql)
{
try
{
using (MySqlConnection connection = GetConnection())
{
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
// 使用参数化查询防止SQL注入
using (MySqlCommand command = new MySqlCommand(sql, connection))
{
return command.ExecuteNonQuery();
}
}
}
catch (MySqlException ex)
{
LogError($"执行自定义指令失败: {ex.Message}");
throw new DatabaseOperationException("执行自定义指令失败", ex);
}
}
// 新增:事务处理方法
public void ExecuteTransaction(Action<MySqlTransaction> action)
{
using (MySqlConnection connection = GetConnection())
{
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
using (var transaction = connection.BeginTransaction())
{
try
{
action(transaction);
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
LogError($"事务执行失败: {ex.Message}");
throw new DatabaseOperationException("事务执行失败", ex);
}
}
}
}
// 新增:批量插入方法
public int BulkInsert(List<Dictionary<string, object>> dataList)
{
if (dataList == null || !dataList.Any())
return 0;
using (MySqlConnection connection = GetConnection())
{
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
using (var transaction = connection.BeginTransaction())
{
try
{
int affectedRows = 0;
string columnsStr = string.Join(",", dataList[0].Keys);
string valuesStr = string.Join(",", dataList[0].Keys.Select(key => $"@{key}"));
foreach (var values in dataList)
{
string query = $"INSERT INTO {tableName} ({columnsStr}) VALUES ({valuesStr})";
using (MySqlCommand command = new MySqlCommand(query, connection, transaction))
{
foreach (var pair in values)
{
command.Parameters.AddWithValue($"@{pair.Key}", pair.Value);
}
affectedRows += command.ExecuteNonQuery();
}
}
transaction.Commit();
return affectedRows;
}
catch (Exception ex)
{
transaction.Rollback();
LogError($"批量插入失败: {ex.Message}");
throw new DatabaseOperationException("批量插入失败", ex);
}
}
}
}
}
}
李枭龙2025-01-13 15:23
AI生成文章:请以上所有知识进行深入分析,确定主要知识点,为每个知识点撰写详细说明并附上具有代表性且带有清晰注释的代码示例,接着根据内容拟定一个准确反映文档核心的标题,最后严格按照 Markdown 格式进行排版,确保文档规范美观,以满足初学者学习使用的需求。
李枭龙2024-09-05 22:04
X Lucas