如何在C#中正确获取Stored Procedure的输出参数
解决C#调用SQL存储过程无法获取输出参数的问题
我看到你遇到的问题了:在SQL Server里执行存储过程能拿到正确的@RecordCount输出值,但在C#的DAC函数里获取后没法传递回主代码,而且你现在的函数只返回DataSet。下面是具体的解决步骤和修改后的代码:
问题核心
你当前的代码已经在ExecuteDataSet之后读取了输出参数,但因为函数返回值只有DataSet,没法把这个整数结果传递给调用方。我们需要修改函数,让它同时返回DataSet和输出参数的值。
解决方案:使用out参数传递输出值
out参数可以让函数在返回主值(DataSet)的同时,把另一个值(记录总数)传递回调用代码。下面是修改后的完整代码:
修改后的DAC函数
public DataSet GetOrderItemPictureByOrderId(int orderID, int PageIndex, out int recordCount) { DataSet dtOrder = new DataSet(); recordCount = 0; // 初始化out参数,避免编译错误 // 连接数据库 Database db = DatabaseFactory.CreateDatabase(CONNECTION_NAME); using (DbCommand cmd = db.GetStoredProcCommand("uspGetOrderItemPicturePageWise")) { // 设置输入参数 db.AddInParameter(cmd, "@OrderID", DbType.Int32, orderID); db.AddInParameter(cmd, "@PageIndex", DbType.Int32, PageIndex); db.AddInParameter(cmd, "@PageSize", DbType.Int32, 6); // 添加输出参数 db.AddOutParameter(cmd, "@RecordCount", DbType.Int32, 4); try { // 执行存储过程获取DataSet dtOrder = db.ExecuteDataSet(cmd); // 执行完成后读取输出参数,注意判断是否为DBNull if (cmd.Parameters["@RecordCount"].Value != DBNull.Value) { recordCount = Convert.ToInt32(cmd.Parameters["@RecordCount"].Value); } } catch (Exception ex) { LogErrors.WriteError(ex); } } return dtOrder; }
修改后的调用代码
int totalRecords; DataSet _ds = _orderPicDAC.GetOrderItemPictureByOrderId(OrderID, PageIndex, out totalRecords); // 现在你可以使用totalRecords变量了,比如用于分页显示 // 示例:Console.WriteLine($"总记录数:{totalRecords}");
关键注意事项
- 读取输出参数的时机:必须在
ExecuteDataSet(或其他执行命令的方法,比如ExecuteNonQuery)执行完成后再读取输出参数,因为只有执行命令后,SQL Server才会把输出参数的值返回给C#的DbCommand对象。 - 处理DBNull:如果存储过程中没有匹配的记录,
@RecordCount可能会返回DBNull,所以一定要先判断再转换,避免抛出InvalidCastException。 - out参数初始化:在C#中,
out参数必须在函数返回前被赋值,所以我们一开始把recordCount初始化为0,确保即使出现异常也不会编译错误。
可选方案:返回自定义类
如果你觉得out参数不够优雅,也可以创建一个自定义类来封装DataSet和记录总数:
public class OrderPictureResult { public DataSet OrderData { get; set; } public int TotalRecords { get; set; } } // 修改DAC函数返回这个类 public OrderPictureResult GetOrderItemPictureByOrderId(int orderID, int PageIndex) { var result = new OrderPictureResult(); result.OrderData = new DataSet(); result.TotalRecords = 0; // 其余逻辑和之前类似,执行完后给result.TotalRecords赋值 return result; } // 调用时: var orderResult = _orderPicDAC.GetOrderItemPictureByOrderId(OrderID, PageIndex); DataSet _ds = orderResult.OrderData; int totalRecords = orderResult.TotalRecords;
这个方案更面向对象,适合复杂场景,但out参数在简单场景下更轻便。
内容的提问来源于stack exchange,提问作者A.Goutam




