You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否使用回调简化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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 20:13:18