能否使用回调简化C#中重复的数据库访问代码?
利用回调机制简化数据库访问代码
完全可以通过委托(回调)机制消除这类重复的数据库访问样板代码。核心思路是将固定的连接创建、命令执行、数据读取逻辑封装为通用方法,把变化的部分(比如参数配置、数据模型映射)通过委托传入。
重构后的SqlDataAccess类
using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; public class SqlDataAccess { // 通用查询执行方法,封装所有样板代码 private List<T> ExecuteQuery<T>(string sqlQuery, string connectionString, Action<SqlCommand> configureCommand = null, Func<SqlDataReader, T> mapReader = null) { List<T> results = new List<T>(); using (SqlConnection conn = new SqlConnection(connectionString)) { conn.Open(); using (SqlCommand cmd = new SqlCommand(sqlQuery, conn)) { // 执行自定义命令配置(如添加参数、设置命令类型) configureCommand?.Invoke(cmd); using (SqlDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { // 将读取器数据映射为目标模型 if (mapReader != null) { results.Add(mapReader(reader)); } } } } } return results; } public List<BookModel> LoadData(string sqlQuery, string connectionString) { return ExecuteQuery<BookModel>(sqlQuery, connectionString, mapReader: ExtractBookFromReader); } public List<BookModel> LoadDataById(int id, string sqlQuery, string connectionString) { return ExecuteQuery<BookModel>(sqlQuery, connectionString, cmd => cmd.Parameters.AddWithValue("@id", id), ExtractBookFromReader); } public List<BookModel> PostNewBook(BookModel newBook, string sqlQuery, string connectionString) { return ExecuteQuery<BookModel>(sqlQuery, connectionString, cmd => { cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@title", newBook.Title); cmd.Parameters.AddWithValue("@author", newBook.Author); cmd.Parameters.AddWithValue("@description", newBook.Description); }, ExtractBookFromReader); } private BookModel ExtractBookFromReader(SqlDataReader reader) { return new BookModel { Id = Convert.ToInt32(reader["id"]), Title = Convert.ToString(reader["title"]), Author = Convert.ToString(reader["author"]), Description = Convert.ToString(reader["description"]) }; } } public class BookModel { public int Id { get; set; } public string Title { get; set; } public string Author { get; set; } public string Description { get; set; } }
关键说明
ExecuteQuery<T>: 核心通用方法,统一处理连接生命周期、命令创建、读取器遍历等固定逻辑,避免重复代码。Action<SqlCommand>: 传入命令的自定义配置逻辑,比如添加查询参数、设置存储过程类型等,灵活适配不同业务场景。Func<SqlDataReader, T>: 传入数据映射逻辑,复用原有的ExtractBookFromReader方法即可完成读取器到模型的转换。- 空安全处理: 使用
?.Invoke()确保无配置需求时(如LoadData方法)不会触发空引用错误。
这种重构方式将重复代码收拢到一处,后续新增数据库操作方法时,只需关注业务相关的参数配置和数据映射,大幅提升代码的简洁性和可维护性。
内容的提问来源于stack exchange,提问作者Jon
相关产品推荐
相关产品推荐

