上一篇
如何高效使用Dapper调用存储过程提升数据库性能?
- 行业动态
- 2025-04-24
- 4835
Dapper通过
DynamicParameters
传递参数,调用存储过程时需设置 commandType: CommandType.StoredProcedure
,使用 Query
或 Execute
方法执行,支持输入输出参数及返回值映射,代码简洁且高效,适用于高性能数据库操作场景。
在.NET开发中,Dapper作为轻量级ORM工具,能显著提升数据库操作效率,本文将通过实际案例演示如何通过Dapper调用SQL Server存储过程,并提供企业级项目中的最佳实践。
准备工作
安装NuGet包
Install-Package Dapper Install-Package System.Data.SqlClient
创建示例存储过程
CREATE PROCEDURE GetEmployeeDetails @EmployeeId INT, @DepartmentCode VARCHAR(10) OUTPUT AS BEGIN SELECT * FROM Employees WHERE Id = @EmployeeId SELECT @DepartmentCode = DepartmentCode FROM Departments WHERE EmployeeId = @EmployeeId END
基础调用方法
using (var connection = new SqlConnection(connectionString)) { var parameters = new DynamicParameters(); parameters.Add("@EmployeeId", 1001); parameters.Add("@DepartmentCode", dbType: DbType.String, direction: ParameterDirection.Output, size: 10); var result = await connection.QueryAsync<Employee>( "GetEmployeeDetails", parameters, commandType: CommandType.StoredProcedure ); var departmentCode = parameters.Get<string>("@DepartmentCode"); }
关键点解析:
- 使用
DynamicParameters
管理输入/输出参数 - 必须指定
CommandType.StoredProcedure
- 通过泛型
QueryAsync<T>
实现强类型映射
高级应用场景
场景1:处理多结果集
using (var multi = connection.QueryMultiple( "GetSalesReport", new { Year = 2025 }, commandType: CommandType.StoredProcedure)) { var summary = multi.Read<SalesSummary>().First(); var details = multi.Read<SalesDetail>().ToList(); }
场景2:事务处理
using (var transaction = connection.BeginTransaction()) { try { connection.Execute( "UpdateInventory", new { ProductId = 501, Quantity = -5 }, transaction: transaction, commandType: CommandType.StoredProcedure ); transaction.Commit(); } catch { transaction.Rollback(); } }
性能优化技巧
参数预编译
var lookup = new Dictionary<int, Employee>(); connection.Query<Employee, Department, Employee>( "GetEmployeeWithDepartment", (e, d) => { if (!lookup.TryGetValue(e.Id, out var emp)) lookup.Add(e.Id, emp = e); emp.Department = d; return emp; }, splitOn: "DepartmentId", commandType: CommandType.StoredProcedure );
异步流式处理
await foreach (var employee in connection.QueryUnbufferedAsync<Employee>( "GetLargeDataset", commandType: CommandType.StoredProcedure)) { // 流式处理数据 }
安全注意事项
- 使用参数化查询防御SQL注入
- 限制存储过程的执行权限
- 对输出参数进行类型验证
- 记录存储过程执行日志
常见问题排查
问题现象 | 解决方案 |
---|---|
参数不生效 | 检查参数名称大小写是否与存储过程一致 |
输出参数为空 | 确认指定了ParameterDirection.Output |
超时问题 | 检查存储过程性能,设置合理CommandTimeout |
类型转换错误 | 确保数据库类型与C#类型匹配 |
引用说明:
- Dapper官方文档:https://github.com/DapperLib/Dapper
- ADO.NET最佳实践:https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/
- SQL Server存储过程指南:https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/