ASP.NET Core调用存储过程返回JSON的代码重构优化方法
现有代码问题说明
- 功能可正常运行,但可维护性差:手动逐字段映射属性,字段数量多的时候极易出现拼写错误,且错误只能在运行期发现,编译期无法校验
- 性能存在优化空间:DataTable属于较重的数据集结构,内存开销高于直接映射为实体类
- 缺少异常处理逻辑:数据库连接失败、存储过程执行报错等场景下会直接抛出未处理异常,返回默认500错误,无容错能力
- 使用的SqlDataAdapter属于老旧API,.NET Core生态下已有更轻量简洁的替代方案
优化方案
方案1:使用Dapper(最推荐,.NET生态通用最佳实践)
Dapper是微软官方推荐的轻量级ORM,专门用于简化数据库查询到实体的映射逻辑,只要存储过程返回的列名和ViewModel属性名一致(大小写不敏感),就可以自动完成映射,无需手动赋值。
操作步骤
- 安装NuGet依赖:
Dapper、Microsoft.Data.SqlClient - 代码可以简化为如下实现:
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
相关产品推荐
相关产品推荐

