C#中DbHelper类的增删改查操作及其应用

目录

(一)

一、DbHelper类基础结构

二、CRUD操作实现

1. 插入数据(Create)

2. 查询数据(Read)

3. 更新数据(Update)

4. 删除数据(Delete)

三、应用场景示例

1. 基础调用

2. 事务处理

四、最佳实践建议

五、完整项目应用结构

一、DbHelper类设计详解

1.1 核心目标

1.2 架构分层

二、基础CRUD操作实现(SQL Server版)

2.1 连接管理优化

2.2 插入操作(Create)

2.3 查询操作(Read)

2.3.1 基础查询

2.3.2 分页查询

2.4 更新操作(Update)

2.5 删除操作(Delete)

三、高级功能扩展

3.1 事务处理

3.2 异步操作

3.3 批量操作优化

四、实际应用场景

4.1 用户管理系统

4.2 订单处理系统

五、最佳实践与优化建议

5.1 连接管理

5.2 性能优化

5.3 安全增强

5.4 日志与监控

六、扩展方向建议

开发说明文档

1. 类设计说明

2. 使用示例

2.1 基础CRUD操作

2.2 事务操作

2.3 批量插入

3. 高级功能说明

4. 配置建议

5. 扩展建议


在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;
        }
    }
}

四、最佳实践建议

  1. 参数化查询:始终使用SqlParameter防止SQL注入
  2. 异步方法:可扩展ExecuteNonQueryAsync等方法提升性能
  3. 连接管理:使用using语句确保连接及时释放
  4. 日志记录:添加执行日志记录功能(如记录SQL语句和执行时间)
  5. 扩展性
    • 支持其他数据库(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. 类设计说明

  1. 架构分层
    • 基础层:封装核心数据库操(ExecuteNonQuery/ExecuteScalar/ExecuteDataTable)
    • 事务层:提供事务管理(BeginTransaction/Commit/Rollback)
    • 扩展层:实现高级功能(BulkInsert/分页查询生成)
  2. 连接管理
    • 使用SqlConnection对象池(通过连接字符串的Pooling=true配置)
    • 支持显式连接管理(Open/Close)和隐式自动管理
  3. 性能优化
    • 集成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);
    }
}

上述操作实现提供了:

  1. 完整的CRUD操作封装
  2. 事务管理支持
  3. 性能监控功能
  4. 批量操作优化
  5. 详细的错误处理
  6. 灵活的扩展点

可根据具体需求选择实现的功能模块,并通过依赖注入容器管理生命周期。建议配合单元测试(如使用xUnit)验证数据库操作的可靠性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值