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

ASP.NET Core调用存储过程返回JSON的代码重构优化方法

现有代码问题说明
  • 功能可正常运行,但可维护性差:手动逐字段映射属性,字段数量多的时候极易出现拼写错误,且错误只能在运行期发现,编译期无法校验
  • 性能存在优化空间:DataTable属于较重的数据集结构,内存开销高于直接映射为实体类
  • 缺少异常处理逻辑:数据库连接失败、存储过程执行报错等场景下会直接抛出未处理异常,返回默认500错误,无容错能力
  • 使用的SqlDataAdapter属于老旧API,.NET Core生态下已有更轻量简洁的替代方案
优化方案

方案1:使用Dapper(最推荐,.NET生态通用最佳实践)

Dapper是微软官方推荐的轻量级ORM,专门用于简化数据库查询到实体的映射逻辑,只要存储过程返回的列名和ViewModel属性名一致(大小写不敏感),就可以自动完成映射,无需手动赋值。

操作步骤

  1. 安装NuGet依赖:Dapper、Microsoft.Data.SqlClient
  2. 代码可以简化为如下实现:
using Dapper;
using Microsoft.Data.SqlClient;
using System.Data;

public IActionResult GetAllBooks()
{
    using var sqlConnection = new SqlConnection(_configuration.GetConnectionString("xxx"));
    var bookList = sqlConnection.Query<BookViewModel>(
        "proc_GetBookList", 
        commandType: CommandType.StoredProcedure
    ).ToList();
    return Json(bookList);
}

如果存储过程需要传参,直接传入匿名类即可,无需手动构造SqlParameter:

var bookList = sqlConnection.Query<BookViewModel>(
    "proc_GetBookList", 
    new { CategoryId = 1, PriceMin = 20 },
    commandType: CommandType.StoredProcedure
).ToList();

方案2:自定义通用映射扩展(不引入第三方库的场景)

如果不希望引入第三方依赖,可以自己通过反射写一套通用的DataTable转实体的扩展方法,写一次即可在所有实体映射场景复用:

通用扩展方法实现

using System.Data;
using System.Reflection;

public static class DataMappingExtensions
{
    public static T ToEntity<T>(this DataRow row) where T : new()
    {
        T entity = new T();
        PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
        
        foreach (PropertyInfo prop in properties)
        {
            if (!row.Table.Columns.Contains(prop.Name) || row[prop.Name] == DBNull.Value)
                continue;
                
            object value = Convert.ChangeType(row[prop.Name], prop.PropertyType);
            prop.SetValue(entity, value);
        }
        return entity;
    }

    public static List<T> ToEntityList<T>(this DataTable dt) where T : new()
    {
        List<T> list = new List<T>();
        foreach (DataRow row in dt.Rows)
        {
            list.Add(row.ToEntity<T>());
        }
        return list;
    }
}

使用方式

你原有代码中的循环赋值逻辑可以替换为一行:

sqlData.Fill(dataTable);
List<BookViewModel> book = dataTable.ToEntityList<BookViewModel>();
其他建议
  • 所有数据库操作建议包裹异常处理逻辑,捕获异常后记录日志,返回业务友好的错误提示
  • 建议将数据库访问逻辑抽离到单独的Repository层,不要和Controller层代码耦合,方便后续维护

内容的提问来源于stack exchange,提问作者user11328958

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 09:54:05