SQL Server存储过程同时返回查询结果与输出参数的问题
解决SQL Server存储过程同时返回结果集与输出参数的问题
这个问题我碰到过,核心原因很明确:当存储过程同时返回查询结果集和输出参数时,输出参数的实际值要等到所有结果集被客户端读取完成(或者DataReader对象被关闭)之后,才会被SQL Server传递到客户端。你当前在using块内直接读取输出参数,此时DataReader还在占用连接处理结果集,参数值还未被填充,所以拿到的是null。
下面给你两种可行的解决方法:
方法一:关闭DataReader后读取输出参数
using块结束时会自动释放并关闭DataReader,此时连接上的结果集处理完成,输出参数的值就会被正确填充。把读取参数的代码移到using块外面即可:
dbContext.Database.OpenConnection(); DbCommand cmd = dbContext.Database.GetDbConnection().CreateCommand(); cmd.CommandTimeout = 15; cmd.CommandText = "GetImmediateManager"; cmd.CommandType = System.Data.CommandType.StoredProcedure; // 定义输出参数 var managerIdParam = new SqlParameter("@managerID", System.Data.SqlDbType.Int); managerIdParam.Direction = ParameterDirection.Output; cmd.Parameters.Add(managerIdParam); List<TaskManagerTask> tasks = new List<TaskManagerTask>(); using (var reader = cmd.ExecuteReader()) { // 读取结果集 tasks = reader.MapToList<TaskManagerTask>(); } // 此时reader已关闭,可正确获取输出参数值 int? managerId = (int?)managerIdParam.Value;
方法二:遍历所有结果集后读取参数
如果需要在DataReader未关闭时读取参数,可以调用reader.NextResult()方法遍历所有结果集(即使只有一个结果集),这个操作会触发SQL Server传递输出参数的值:
dbContext.Database.OpenConnection(); DbCommand cmd = dbContext.Database.GetDbConnection().CreateCommand(); cmd.CommandTimeout = 15; cmd.CommandText = "GetImmediateManager"; cmd.CommandType = System.Data.CommandType.StoredProcedure; var managerIdParam = new SqlParameter("@managerID", System.Data.SqlDbType.Int); managerIdParam.Direction = ParameterDirection.Output; cmd.Parameters.Add(managerIdParam); using (var reader = cmd.ExecuteReader()) { tasks = reader.MapToList<TaskManagerTask>(); // 移动到下一个结果集(无更多结果时返回false,但会触发参数填充) reader.NextResult(); // 现在可以读取输出参数了 int? managerId = (int?)managerIdParam.Value; }
另外补充一点:你的存储过程本身没有问题,不需要修改,只需要调整C#代码中读取输出参数的时机即可。
内容的提问来源于stack exchange,提问作者Robert
相关产品推荐
相关产品推荐

