You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在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}");

关键注意事项

  1. 读取输出参数的时机:必须在ExecuteDataSet(或其他执行命令的方法,比如ExecuteNonQuery)执行完成后再读取输出参数,因为只有执行命令后,SQL Server才会把输出参数的值返回给C#的DbCommand对象。
  2. 处理DBNull:如果存储过程中没有匹配的记录,@RecordCount可能会返回DBNull,所以一定要先判断再转换,避免抛出InvalidCastException
  3. 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

火山引擎 最新活动