目录
在C#开发中,DbHelper
类是封装数据库操作的常用工具类,主要用于简化数据访问层的代码。以下是关于DbHelper
类实现增删改查(CRUD)的完整示例及说明:
(一)
一、DbHelper类基础结构
csharp
using System.Data; using System.Data.SqlClient; public class DbHelper { private readonly string _connectionString; // 构造函数(通过配置文件读取连接字符串) public DbHelper(string connectionString) { _connectionString = connectionString; } // 执行非查询操作(增删改) public int ExecuteNonQuery(string sql, SqlParameter[] parameters = null) { using (SqlConnection conn = new SqlConnection(_connectionString)) { conn.Open(); using (SqlCommand cmd = new SqlCommand(sql, conn)) { if (parameters != null) { cmd.Parameters.AddRange(parameters); } return cmd.ExecuteNonQuery(); } } } // 执行查询操作(返回单个值) public object ExecuteScalar(string sql, SqlParameter[] parameters = null) { using (SqlConnection conn = new SqlConnection(_connectionString)) { conn.Open(); using (SqlCommand cmd = new SqlCommand(sql, conn)) { if (parameters != null) { cmd.Parameters.AddRange(parameters); } return cmd.ExecuteScalar(); } } } // 执行查询操作(返回数据表) public DataTable ExecuteDataTable(string sql, SqlParameter[] parameters = null) { DataTable dt = new DataTable(); using (SqlConnection conn = new SqlConnection(_connectionString)) { conn.Open(); using (SqlCommand cmd = new SqlCommand(sql, conn)) { if (parameters != null) { cmd.Parameters.AddRange(parameters); } using (SqlDataAdapter adapter = new SqlDataAdapter(cmd)) { adapter.Fill(dt); } } } return dt; } }
二、CRUD操作实现
1. 插入数据(Create)
csharp
public int InsertUser(string name, int age) { string sql = "INSERT INTO Users (Name, Age) VALUES (@Name, @Age); SELECT SCOPE_IDENTITY();"; SqlParameter[] parameters = { new SqlParameter("@Name", SqlDbType.NVarChar) { Value = name }, new SqlParameter("@Age", SqlDbType.Int) { Value = age } }; return Convert.ToInt32(ExecuteScalar(sql, parameters)); }
2. 查询数据(Read)
csharp
public DataTable GetAllUsers() { string sql = "SELECT * FROM Users"; return ExecuteDataTable(sql); } public DataTable GetUserById(int id) { string sql = "SELECT * FROM Users WHERE Id = @Id"; SqlParameter[] parameters = { new SqlParameter("@Id", SqlDbType.Int) { Value = id } }; return ExecuteDataTable(sql, parameters); }
3. 更新数据(Update)
csharp
public int UpdateUserName(int id, string newName) { string sql = "UPDATE Users SET Name = @Name WHERE Id = @Id"; SqlParameter[] parameters = { new SqlParameter("@Name", SqlDbType.NVarChar) { Value = newName }, new SqlParameter("@Id", SqlDbType.Int) { Value = id } }; return ExecuteNonQuery(sql, parameters); }
4. 删除数据(Delete)
csharp
public int DeleteUser(int id) { string sql = "DELETE FROM Users WHERE Id = @Id"; SqlParameter[] parameters = { new SqlParameter("@Id", SqlDbType.Int) { Value = id } }; return ExecuteNonQuery(sql, parameters); }
三、应用场景示例
1. 基础调用
csharp
// 初始化DbHelper(连接字符串从配置文件读取) DbHelper dbHelper = new DbHelper(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString); // 插入数据 int newId = dbHelper.InsertUser("张三", 25); // 查询数据 DataTable users = dbHelper.GetAllUsers(); // 更新数据 dbHelper.UpdateUserName(1, "李四"); // 删除数据 dbHelper.DeleteUser(2);
2. 事务处理
csharp
using (SqlConnection conn = new SqlConnection(_connectionString)) { conn.Open(); using (SqlTransaction transaction = conn.BeginTransaction()) { try { // 在事务中执行多个操作 dbHelper.ExecuteNonQuery("UPDATE Accounts SET Balance -= 100 WHERE Id = 1", conn, transaction); dbHelper.ExecuteNonQuery("UPDATE Accounts SET Balance += 100 WHERE Id = 2", conn, transaction); transaction.Commit(); } catch { transaction.Rollback(); throw; } } }
四、最佳实践建议
- 参数化查询:始终使用
SqlParameter
防止SQL注入 - 异步方法:可扩展
ExecuteNonQueryAsync
等方法提升性能 - 连接管理:使用
using
语句确保连接及时释放 - 日志记录:添加执行日志记录功能(如记录SQL语句和执行时间)
- 扩展性:
- 支持其他数据库(MySQL/Oracle)
- 集成ORM框架(如Dapper)
- 添加缓存机制
五、完整项目应用结构
├── DataAccess/ |
│ ├── DbHelper.cs # 数据库工具类 |
│ ├── UserRepository.cs # 具体业务仓库 |
│ └── IRepository.cs # 仓储接口 |
├── Models/ |
│ └── User.cs # 数据模型 |
└── App.config # 配置文件(连接字符串) |
注:通过这种封装方式,可以显著提升代码复用性和可维护性,同时降低业务逻辑层与数据访问层的耦合度。
(二)
一、DbHelper类设计详解
1.1 核心目标
- 封装重复代码:将连接管理、命令执行、异常处理等通用操作封装
- 提升可维护性:通过统一入口降低数据库操作分散带来的维护成本
- 增强安全性:强制使用参数化查询防止SQL注入
- 支持扩展性:预留接口支持不同数据库类型(SQL Server/MySQL/Oracle)
1.2 架构分层
项目结构示例:
MyProject.Data/
├── Core/
│ ├── DbHelper.cs # 基础数据库操作
│ ├── SqlServerHelper.cs # SQL Server扩展
│ └── MySqlHelper.cs # MySQL扩展
├── Repositories/
│ ├── IUserRepository.cs # 仓储接口
│ └── UserRepository.cs # 具体实现
└── Config/
└── DatabaseConfig.cs # 配置管理
二、基础CRUD操作实现(SQL Server版)
2.1 连接管理优化
csharp
public class SqlServerHelper : DbHelper { private readonly string _connectionString; // 从配置文件读取连接字符串(支持加密) public SqlServerHelper(string connectionStringName = "DefaultConnection") { var config = Configuration.GetConnectionString(connectionStringName); _connectionString = Decrypt(config); // 自定义解密方法 } // 重写基础方法(使用SqlConnection) protected override IDbConnection CreateConnection() { return new SqlConnection(_connectionString); } }
2.2 插入操作(Create)
csharp
public int InsertUser(User user) { const string sql = @" INSERT INTO Users (UserName, Email, CreatedAt) VALUES (@UserName, @Email, @CreatedAt); SELECT SCOPE_IDENTITY();"; // 返回自增ID var parameters = new[] { new SqlParameter("@UserName", SqlDbType.NVarChar, 50) { Value = user.UserName }, new SqlParameter("@Email", SqlDbType.NVarChar, 100) { Value = user.Email }, new SqlParameter("@CreatedAt", SqlDbType.DateTime2) { Value = DateTime.UtcNow } }; return Convert.ToInt32(ExecuteScalar(sql, parameters)); }
2.3 查询操作(Read)
2.3.1 基础查询
csharp
public User GetUserById(int id) { const string sql = @" SELECT Id, UserName, Email, CreatedAt, LastLogin FROM Users WHERE Id = @Id"; var parameters = new[] { new SqlParameter("@Id", SqlDbType.Int) { Value = id } }; using var dt = ExecuteDataTable(sql, parameters); return dt.Rows.Count > 0 ? MapToUser(dt.Rows[0]) : null; } private User MapToUser(DataRow row) { return new User { Id = Convert.ToInt32(row["Id"]), UserName = row["UserName"].ToString(), Email = row["Email"].ToString(), CreatedAt = Convert.ToDateTime(row["CreatedAt"]), LastLogin = row["LastLogin"] == DBNull.Value ? (DateTime?)null : Convert.ToDateTime(row["LastLogin"]) }; }
2.3.2 分页查询
csharp
public PagedResult<User> GetPagedUsers(int pageIndex, int pageSize) { const string countSql = "SELECT COUNT(*) FROM Users"; const string dataSql = @" SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (ORDER BY CreatedAt DESC) AS RowNum FROM Users ) AS T WHERE RowNum BETWEEN @Start AND @End"; var total = Convert.ToInt32(ExecuteScalar(countSql)); var parameters = new[] { new SqlParameter("@Start", SqlDbType.Int) { Value = (pageIndex - 1) * pageSize + 1 }, new SqlParameter("@End", SqlDbType.Int) { Value = pageIndex * pageSize } }; var data = ExecuteDataTable(dataSql, parameters); return new PagedResult<User> { TotalItems = total, Items = data.AsEnumerable().Select(MapToUser).ToList(), PageIndex = pageIndex, PageSize = pageSize }; }
2.4 更新操作(Update)
csharp
public int UpdateUserEmail(int userId, string newEmail) { const string sql = @" UPDATE Users SET Email = @Email, LastLogin = @LastLogin WHERE Id = @Id"; var parameters = new[] { new SqlParameter("@Email", SqlDbType.NVarChar, 100) { Value = newEmail }, new SqlParameter("@LastLogin", SqlDbType.DateTime2) { Value = DateTime.UtcNow }, new SqlParameter("@Id", SqlDbType.Int) { Value = userId } }; return ExecuteNonQuery(sql, parameters); }
2.5 删除操作(Delete)
csharp
public int DeleteUser(int id, bool isSoftDelete = false) { string sql = isSoftDelete ? "UPDATE Users SET IsDeleted = 1 WHERE Id = @Id" : "DELETE FROM Users WHERE Id = @Id"; var parameters = new[] { new SqlParameter("@Id", SqlDbType.Int) { Value = id } }; return ExecuteNonQuery(sql, parameters); }
三、高级功能扩展
3.1 事务处理
csharp
public void TransferBalance(int fromId, int toId, decimal amount) { using var conn = (SqlConnection)CreateConnection(); conn.Open(); using var transaction = conn.BeginTransaction(); try { // 执行多个操作 ExecuteNonQuery( "UPDATE Accounts SET Balance -= @Amount WHERE Id = @FromId", new[] { new SqlParameter("@Amount", amount), new SqlParameter("@FromId", fromId) }, conn, transaction ); ExecuteNonQuery( "UPDATE Accounts SET Balance += @Amount WHERE Id = @ToId", new[] { new SqlParameter("@Amount", amount), new SqlParameter("@ToId", toId) }, conn, transaction ); transaction.Commit(); } catch { transaction.Rollback(); throw; } }
3.2 异步操作
csharp
public async Task<int> InsertUserAsync(User user) { const string sql = @" INSERT INTO Users (UserName, Email) VALUES (@UserName, @Email)"; var parameters = new[] { new SqlParameter("@UserName", user.UserName), new SqlParameter("@Email", user.Email) }; using var conn = (SqlConnection)CreateConnection(); await conn.OpenAsync(); using var cmd = conn.CreateCommand(); cmd.CommandText = sql; cmd.Parameters.AddRange(parameters); return await cmd.ExecuteNonQueryAsync(); }
3.3 批量操作优化
csharp
public int BulkInsertUsers(IEnumerable<User> users) { const string sql = "INSERT INTO Users (UserName, Email) VALUES (@UserName, @Email)"; using var conn = (SqlConnection)CreateConnection(); conn.Open(); using var transaction = conn.BeginTransaction(); using var cmd = conn.CreateCommand(); cmd.Transaction = transaction; cmd.CommandText = sql; var parameters = new[] { new SqlParameter("@UserName", SqlDbType.NVarChar), new SqlParameter("@Email", SqlDbType.NVarChar) }; cmd.Parameters.AddRange(parameters); int count = 0; foreach (var user in users) { cmd.Parameters[0].Value = user.UserName; cmd.Parameters[1].Value = user.Email; count += await cmd.ExecuteNonQueryAsync(); } transaction.Commit(); return count; }
四、实际应用场景
4.1 用户管理系统
csharp
// 业务逻辑层调用示例 public class UserService { private readonly IUserRepository _userRepo; public UserService(IUserRepository userRepo) { _userRepo = userRepo; } public UserRegistrationResult RegisterUser(UserRegistrationModel model) { // 参数验证 if (string.IsNullOrWhiteSpace(model.Email)) return UserRegistrationResult.InvalidEmail; // 检查邮箱是否已存在 if (_userRepo.GetUserByEmail(model.Email) != null) return UserRegistrationResult.EmailExists; // 创建用户实体 var user = new User { UserName = model.UserName, Email = model.Email.ToLower(), PasswordHash = BCrypt.Net.BCrypt.HashPassword(model.Password) }; // 执行插入 var newId = _userRepo.InsertUser(user); if (newId > 0) { // 发送验证邮件(异步) _ = EmailService.SendVerificationEmailAsync(user.Email); return UserRegistrationResult.Success; } return UserRegistrationResult.Failure; } }
4.2 订单处理系统
csharp
public class OrderProcessor { private readonly IOrderRepository _orderRepo; private readonly IInventoryRepository _inventoryRepo; public OrderProcessor(IOrderRepository orderRepo, IInventoryRepository inventoryRepo) { _orderRepo = orderRepo; _inventoryRepo = inventoryRepo; } public bool ProcessOrder(int orderId) { using var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled); try { var order = _orderRepo.GetOrderDetails(orderId); if (order == null || order.Status != OrderStatus.Pending) return false; // 验证库存 if (!_inventoryRepo.CheckStock(order.Items)) throw new InvalidOperationException("Insufficient stock"); // 扣减库存 _inventoryRepo.DeductStock(order.Items); // 更新订单状态 _orderRepo.UpdateOrderStatus(orderId, OrderStatus.Processing); scope.Complete(); return true; } catch { scope.Dispose(); return false; } } }
五、最佳实践与优化建议
5.1 连接管理
- 连接池配置(App.config示例):
xml
<connectionStrings> <add name="DefaultConnection" connectionString="Server=.;Database="数据库名";Integrated Security=True;Pooling=true;Max Pool Size=100;Min Pool Size=5;" providerName="System.Data.SqlClient"/> </connectionStrings>
5.2 性能优化
-
参数嗅探问题:
csharp
// 使用OPTION (RECOMPILE)
const string sql = @"
SELECT * FROM Products
WHERE Price > @MinPrice
OPTION (RECOMPILE)";
- 查询计划缓存:
csharp
// 使用参数化查询避免计划缓存膨胀 var cmd = new SqlCommand("SELECT * FROM Users WHERE UserName LIKE @NamePattern"); cmd.Parameters.AddWithValue("@NamePattern", "A%");
5.3 安全增强
-
动态数据掩码(SQL Server 2016+):
sql
ALTER TABLE Users ALTER COLUMN Email ADD MASKED WITH (FUNCTION = 'email()');
行级安全性:
sql
CREATE SECURITY POLICY UserFilterPolicy ADD FILTER PREDICATE dbo.fn_securitypredicate(UserId) ON dbo.Orders;
5.4 日志与监控
csharp
public class LoggingDbHelper : DbHelper { private readonly ILogger _logger; public LoggingDbHelper(string connectionString, ILogger logger) : base(connectionString) { _logger = logger; } protected override void OnBeforeExecute(string sql, SqlParameter[] parameters) { _logger.LogDebug($"Executing SQL: {sql}"); if (parameters != null) { foreach (var p in parameters) { _logger.LogTrace($"Param: {p.ParameterName} = {p.Value}"); } } } protected override void OnAfterExecute(string sql, long elapsedMilliseconds) { _logger.LogInformation($"SQL executed in {elapsedMilliseconds}ms: {sql}"); } }
六、扩展方向建议
集成ORM:
csharp
// 使用Dapper扩展 public IEnumerable<User> GetActiveUsers() { return Connection.Query<User>( "SELECT * FROM Users WHERE IsActive = 1", commandType: CommandType.Text ); }
支持多数据库:
csharp
public interface IDbHelper { int ExecuteNonQuery(string sql, object parameters = null); T ExecuteScalar<T>(string sql, object parameters = null); IEnumerable<T> Query<T>(string sql, object parameters = null); } public class SqlServerHelper : IDbHelper { /* ... */ } public class MySqlHelper : IDbHelper { /* ... */ }
添加缓存层:
csharp
public class CachedDbHelper : DbHelper { private readonly IMemoryCache _cache; public CachedDbHelper(string connectionString, IMemoryCache cache) : base(connectionString) { _cache = cache; } public DataTable GetCachedUsers(string cacheKey, TimeSpan expiration) { return _cache.GetOrCreate(cacheKey, entry => { entry.SetAbsoluteExpiration(expiration); return base.ExecuteDataTable("SELECT * FROM Users"); }); } }
(三)
完整版C# DbHelper类:
csharp
using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; namespace DataAccess.Core { /// <summary> /// 数据库操作基类(SQL Server实现) /// </summary> /// <remarks> /// 设计目标: /// 1. 封装基础CRUD操作 /// 2. 统一异常处理机制 /// 3. 支持事务和连接管理 /// 4. 提供可扩展的架构 /// </remarks> public abstract class DbHelper : IDisposable { #region 私有字段 /// <summary> /// 数据库连接字符串(从配置文件读取) /// </summary> private readonly string _connectionString; /// <summary> /// 数据库连接对象(使用using自动释放) /// </summary> private SqlConnection _connection; /// <summary> /// 事务对象(用于支持事务操作) /// </summary> private SqlTransaction _transaction; /// <summary> /// 是否已释放资源 /// </summary> private bool _disposed = false; #endregion #region 构造函数 /// <summary> /// 初始化数据库帮助类 /// </summary> /// <param name="connectionStringName">配置文件中的连接字符串名称(默认:DefaultConnection)</param> protected DbHelper(string connectionStringName = "DefaultConnection") { // 从配置文件读取连接字符串(示例:App.config/Web.config) _connectionString = ConfigurationManager.ConnectionStrings[connectionStringName]?.ConnectionString ?? throw new ArgumentNullException($"未找到名为'{connectionStringName}'的连接字符串"); // 初始化连接对象(延迟创建) _connection = new SqlConnection(_connectionString); } #endregion #region 基础方法 /// <summary> /// 打开数据库连接(自动管理连接生命周期) /// </summary> /// <remarks> /// 使用建议: /// 1. 在需要执行多个操作时保持连接打开 /// 2. 使用using语句确保自动释放 /// </remarks> /// <exception cref="InvalidOperationException">连接已打开时抛出</exception> public void OpenConnection() { if (_connection.State != ConnectionState.Closed) throw new InvalidOperationException("连接已处于打开状态"); _connection.Open(); } /// <summary> /// 关闭数据库连接 /// </summary> public void CloseConnection() { if (_connection.State == ConnectionState.Open) { _connection.Close(); } } /// <summary> /// 创建新的SqlCommand对象 /// </summary> /// <param name="cmdText">SQL语句或存储过程名称</param> /// <param name="commandType">命令类型(默认:Text)</param> /// <returns>配置好的SqlCommand对象</returns> protected SqlCommand CreateCommand(string cmdText, CommandType commandType = CommandType.Text) { var cmd = _connection.CreateCommand(); cmd.CommandText = cmdText; cmd.CommandType = commandType; // 如果存在事务,自动关联 if (_transaction != null) { cmd.Transaction = _transaction; } return cmd; } #endregion #region 核心CRUD操作 /// <summary> /// 执行非查询操作(INSERT/UPDATE/DELETE) /// </summary> /// <param name="sql">SQL语句</param> /// <param name="parameters">参数集合</param> /// <param name="commandTimeout">命令超时时间(秒)</param> /// <returns>受影响的行数</returns> /// <exception cref="DbOperationException">包含错误信息的自定义异常</exception> public int ExecuteNonQuery(string sql, IEnumerable<SqlParameter> parameters = null, int commandTimeout = 30) { SqlCommand cmd = null; try { // 性能计数器(可选) using (var stopwatch = Stopwatch.StartNew()) { cmd = CreateCommand(sql); cmd.CommandTimeout = commandTimeout; // 添加参数 if (parameters != null) { cmd.Parameters.AddRange(parameters.ToArray()); } // 执行并记录性能 var result = cmd.ExecuteNonQuery(); LogPerformance(sql, stopwatch.ElapsedMilliseconds, parameters); return result; } } catch (SqlException ex) { // 统一异常处理 throw new DbOperationException($"SQL执行失败:{sql}", ex, cmd); } } /// <summary> /// 执行查询并返回首行首列的值 /// </summary> /// <typeparam name="T">返回值类型</typeparam> /// <param name="sql">SQL语句</param> /// <param name="parameters">参数集合</param> /// <param name="commandTimeout">命令超时时间</param> /// <returns>查询结果</returns> public T ExecuteScalar<T>(string sql, IEnumerable<SqlParameter> parameters = null, int commandTimeout = 30) { using (var cmd = CreateCommand(sql)) { cmd.CommandTimeout = commandTimeout; if (parameters != null) { cmd.Parameters.AddRange(parameters.ToArray()); } var result = cmd.ExecuteScalar(); return result == DBNull.Value ? default : (T)result; } } /// <summary> /// 执行查询并返回数据表 /// </summary> /// <param name="sql">SQL语句</param> /// <param name="parameters">参数集合</param> /// <param name="commandTimeout">命令超时时间</param> /// <returns>包含查询结果的DataTable</returns> public DataTable ExecuteDataTable(string sql, IEnumerable<SqlParameter> parameters = null, int commandTimeout = 30) { using (var cmd = CreateCommand(sql)) { cmd.CommandTimeout = commandTimeout; if (parameters != null) { cmd.Parameters.AddRange(parameters.ToArray()); } var dt = new DataTable(); using (var adapter = new SqlDataAdapter(cmd)) { adapter.Fill(dt); } return dt; } } #endregion #region 高级功能 /// <summary> /// 开始数据库事务 /// </summary> /// <param name="isolationLevel">事务隔离级别(默认:ReadCommitted)</param> /// <returns>事务对象(用于Commit/Rollback)</returns> public SqlTransaction BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted) { if (_transaction != null) throw new InvalidOperationException("事务已开始"); OpenConnection(); _transaction = _connection.BeginTransaction(isolationLevel); return _transaction; } /// <summary> /// 提交当前事务 /// </summary> public void CommitTransaction() { _transaction?.Commit(); _transaction = null; } /// <summary> /// 回滚当前事务 /// </summary> public void RollbackTransaction() { _transaction?.Rollback(); _transaction = null; } /// <summary> /// 执行批量插入操作(使用SqlBulkCopy) /// </summary> /// <typeparam name="T">数据类型</typeparam> /// <param name="dataTable">数据表</param> /// <param name="tableName">目标表名</param> /// <param name="batchSize">批量大小(默认:5000)</param> public void BulkInsert<T>(DataTable dataTable, string tableName, int batchSize = 5000) { using (var bulkCopy = new SqlBulkCopy(_connection, SqlBulkCopyOptions.Default, _transaction)) { bulkCopy.DestinationTableName = tableName; bulkCopy.BatchSize = batchSize; bulkCopy.WriteToServer(dataTable); } } #endregion #region 辅助方法 /// <summary> /// 记录SQL执行性能 /// </summary> /// <param name="sql">执行的SQL语句</param> /// <param name="elapsedMilliseconds">耗时(毫秒)</param> /// <param name="parameters">使用的参数</param> private void LogPerformance(string sql, long elapsedMilliseconds, IEnumerable<SqlParameter> parameters) { // 实际项目中可集成日志框架(如Serilog、NLog) Trace.WriteLine($"[SQL Performance] {sql} executed in {elapsedMilliseconds}ms"); if (elapsedMilliseconds > 1000) { Trace.TraceWarning($"Slow query detected: {sql}"); } // 调试时输出参数信息 #if DEBUG if (parameters != null) { foreach (var p in parameters) { Trace.WriteLine($"Param: {p.ParameterName} = {p.Value} ({p.SqlDbType})"); } } #endif } /// <summary> /// 生成分页查询SQL /// </summary> /// <param name="baseSql">基础查询语句</param> /// <param name="orderBy">排序字段</param> /// <param name="pageIndex">页码(从1开始)</param> /// <param name="pageSize">每页大小</param> /// <returns>分页SQL语句</returns> public static string GeneratePagedSql(string baseSql, string orderBy, int pageIndex, int pageSize) { if (pageIndex < 1) pageIndex = 1; if (pageSize < 1) pageSize = 10; var startRow = (pageIndex - 1) * pageSize + 1; var endRow = pageIndex * pageSize; return $@" WITH PagedData AS ( SELECT *, ROW_NUMBER() OVER (ORDER BY {orderBy}) AS RowNum FROM ({baseSql}) AS SubQuery ) SELECT * FROM PagedData WHERE RowNum BETWEEN {startRow} AND {endRow}"; } #endregion #region IDisposable 实现 /// <summary> /// 释放非托管资源 /// </summary> public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// <summary> /// 释放资源 /// </summary> /// <param name="disposing">是否正在释放托管资源</param> protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) { // 释放托管资源 _transaction?.Dispose(); _connection?.Dispose(); } // 释放非托管资源 _disposed = true; } } #endregion } #region 自定义异常 /// <summary> /// 数据库操作异常(包含执行的SQL语句) /// </summary> public class DbOperationException : Exception { /// <summary> /// 执行的SQL语句 /// </summary> public string ExecutedSql { get; } /// <summary> /// 使用的参数 /// </summary> public SqlParameter[] Parameters { get; } public DbOperationException(string message, Exception innerException, SqlCommand command) : base(message, innerException) { ExecutedSql = command?.CommandText; Parameters = command?.Parameters?.Cast<SqlParameter>().ToArray(); } } #endregion }
C# DbHelper
类实现,涵盖从基础功能到高级特性的完整实现,并附加详细开发说明:
开发说明文档
1. 类设计说明
- 架构分层:
- 基础层:封装核心数据库操(ExecuteNonQuery/ExecuteScalar/ExecuteDataTable)
- 事务层:提供事务管理(BeginTransaction/Commit/Rollback)
- 扩展层:实现高级功能(BulkInsert/分页查询生成)
- 连接管理:
- 使用
SqlConnection
对象池(通过连接字符串的Pooling=true
配置) - 支持显式连接管理(Open/Close)和隐式自动管理
- 使用
- 性能优化:
- 集成
Stopwatch
进行性能计时 - 自动记录慢查询(>1秒)
- 支持批量操作(SqlBulkCopy)
- 集成
2. 使用示例
2.1 基础CRUD操作
csharp
// 初始化(从配置文件读取连接字符串) using var dbHelper = new SqlServerHelper(); // 插入数据 var insertParams = new[] { new SqlParameter("@Name", "张三"), new SqlParameter("@Age", 25) }; var newId = dbHelper.ExecuteScalar<int>( "INSERT INTO Users (Name, Age) VALUES (@Name, @Age); SELECT SCOPE_IDENTITY();", insertParams ); // 查询数据 var users = dbHelper.ExecuteDataTable("SELECT * FROM Users WHERE Age > @MinAge", new[] { new SqlParameter("@MinAge", 20) }); // 更新数据 var updateParams = new[] { new SqlParameter("@NewName", "李四"), new SqlParameter("@UserId", newId) }; dbHelper.ExecuteNonQuery( "UPDATE Users SET Name = @NewName WHERE Id = @UserId", updateParams ); // 删除数据 dbHelper.ExecuteNonQuery( "DELETE FROM Users WHERE Id = @Id", new[] { new SqlParameter("@Id", newId) } );
2.2 事务操作
csharp
using (var dbHelper = new SqlServerHelper()) { var transaction = dbHelper.BeginTransaction(); try { // 执行多个操作 dbHelper.ExecuteNonQuery( "UPDATE Accounts SET Balance = Balance - 100 WHERE Id = 1", transaction: transaction ); dbHelper.ExecuteNonQuery( "UPDATE Accounts SET Balance = Balance + 100 WHERE Id = 2", transaction: transaction ); transaction.Commit(); } catch { transaction.Rollback(); throw; } }
2.3 批量插入
csharp
var dt = new DataTable(); dt.Columns.Add("Name", typeof(string)); dt.Columns.Add("Age", typeof(int)); dt.Rows.Add("王五", 30); dt.Rows.Add("赵六", 28); using (var dbHelper = new SqlServerHelper()) { dbHelper.BulkInsert(dt, "Users"); }
3. 高级功能说明
分页查询生成:
csharp
var baseSql = "SELECT * FROM Products WHERE Price > 100"; var pagedSql = DbHelper.GeneratePagedSql(baseSql, "CreatedAt DESC", 2, 10); // 生成的分页SQL包含ROW_NUMBER()窗口函数
性能监控:
- 自动记录执行时间超过1秒的慢查询
- 调试模式下输出完整参数信息
异常处理:
- 自定义
DbOperationException
包含执行的SQL和参数信息 - 保留原始异常链(InnerException)
4. 配置建议
在App.config
中配置连接字符串:
XML
<configuration> <connectionStrings> <add name="DefaultConnection" connectionString="Server=.;Database=MyDB;Integrated Security=True;Pooling=true;Max Pool Size=100;" providerName="System.Data.SqlClient"/> </connectionStrings> </configuration>
5. 扩展建议
- 集成依赖注入:
csharp
// 在Startup.cs中注册 services.AddScoped<DbHelper, SqlServerHelper>();
- 添加缓存层:
csharp
public class CachedDbHelper : DbHelper { private readonly IMemoryCache _cache; public CachedDbHelper(IMemoryCache cache) : base() { _cache = cache; } public new DataTable ExecuteDataTable(string sql, ...) { var cacheKey = $"SQL_{sql.GetHashCode()}"; return _cache.GetOrCreate(cacheKey, entry => { entry.SetAbsoluteExpiration(TimeSpan.FromMinutes(5)); return base.ExecuteDataTable(sql, ...); }); } }
- 添加缓存层:
csharp
public class CachedDbHelper : DbHelper { private readonly IMemoryCache _cache; public CachedDbHelper(IMemoryCache cache) : base() { _cache = cache; } public new DataTable ExecuteDataTable(string sql, ...) { var cacheKey = $"SQL_{sql.GetHashCode()}"; return _cache.GetOrCreate(cacheKey, entry => { entry.SetAbsoluteExpiration(TimeSpan.FromMinutes(5)); return base.ExecuteDataTable(sql, ...); }); } }
支持其他数据库:
csharp
public class MySqlHelper : DbHelper { protected override IDbConnection CreateConnection() { return new MySqlConnection(_connectionString); } }
上述操作实现提供了:
- 完整的CRUD操作封装
- 事务管理支持
- 性能监控功能
- 批量操作优化
- 详细的错误处理
- 灵活的扩展点
可根据具体需求选择实现的功能模块,并通过依赖注入容器管理生命周期。建议配合单元测试(如使用xUnit)验证数据库操作的可靠性。