如何通过存储过程与Dapper传递变量?遇类型转换错误求助
问题分析与修复方案
核心错误:参数传递类型不匹配
你在CalculateAVG方法里创建了DynamicParameters对象并传递给GetUptimeAvg,但GetUptimeAvg的参数定义是int Websiteid,直接把DynamicParameters实例传给需要int的方法,必然会触发类型转换错误。
一步步修复代码
1. 修正模型服务代码
直接传递int类型的response.Websiteid,无需额外包装DynamicParameters,同时把async void改为async Task避免异步上下文问题:
public async Task CalculateAVG(UptimeModel response) { var websites = await _db.GetUptimeAvg(response.Websiteid); _logger.LogInformation($"Average is {websites}"); }
2. 修正数据服务代码
将传入的Websiteid正确传递给存储过程,确保Dapper调用时携带参数:
public async Task<WebsiteModel?> GetUptimeAvg(int Websiteid) { var results = await _db.LoadData<WebsiteModel, dynamic>( storedProcedure: "dbo.spUptimes_GetAvg", new { Websiteid }); // 参数名称与存储过程的@websiteid匹配(Dapper支持大小写不敏感) return results.FirstOrDefault(); }
3. 修正存储过程逻辑
- 移除硬编码的
SET @websiteid = 1;,否则传入的参数会被覆盖 - 修正统计逻辑:原代码把网站ID和状态字段混淆,需按网站ID筛选后统计不同状态的数量
- 添加结果返回语句,让Dapper能映射到
WebsiteModel - 处理除数为0的异常情况
修改后的存储过程:
CREATE PROCEDURE [dbo].[spUptimes_GetAvg] @websiteid int AS BEGIN SET ARITHABORT OFF SET ANSI_WARNINGS OFF DECLARE @uptime float DECLARE @downtime float DECLARE @uptimeavg float -- 统计指定网站的在线状态数量(假设Status=1代表在线) SET @uptime = (SELECT COUNT(Status) FROM dbo.[Uptimes] WHERE Websiteid = @websiteid AND Status = 1) -- 统计指定网站的离线状态数量(假设Status=0代表离线) SET @downtime = (SELECT COUNT(Status) FROM dbo.[Uptimes] WHERE Websiteid = @websiteid AND Status = 0) -- 避免除以0的情况 SET @uptimeavg = CASE WHEN (@uptime + @downtime) = 0 THEN 0 ELSE (@uptime / (@uptime + @downtime) * 100) END -- 返回结果供Dapper映射 SELECT @uptimeavg AS UptimeAvg, @websiteid AS Websiteid END
4. 对齐接口与实现
确保接口定义和方法实现一致:
Task<WebsiteModel?> GetUptimeAvg(int Websiteid);
额外注意事项
async void仅适用于事件处理程序,普通异步方法必须用async Task,否则会导致异步资源泄漏- 确保
WebsiteModel包含存储过程返回的字段(如UptimeAvg、Websiteid),否则Dapper无法完成对象映射
内容的提问来源于stack exchange,提问作者Rahbit
相关产品推荐
相关产品推荐

