首页 > 解决方案 > 使用 ADO,使用 SqlDataAdapter.FillSchema 清除 @ReturnValues 和其他标记为输出的存储过程参数

问题描述

[编辑 - 答案的解释在问题的底部,因为从接受的答案中微妙之处并不完全明显。]

原始问题:

在我做出进一步努力之前,我正在寻找一个快速的“是的,这种方法应该可行”的答案。

设想:

我在期待什么?

我看到了什么?

我做了什么研究?

我需要询问 SO 社区这是否可能。那么 - 是否可以OUTPUT从与 一起使用的存储过程中收集参数值SqlDatAdapter.DataSet.Fill()

如果答案是肯定的并且没有简单的示例,那么我会将我的代码缩减为一个有代表性的案例,并将其发布在这里(希望)用于社区调试。

编辑感谢@NDJ 和提供的示例代码,我能够确认SqlDatAdapter.DataSet.Fill() 不会干扰存储过程的返回值。然后我能够继续发现我的问题是由立即调用引起的SqlDatAdapter.DataSet.FillScheam()。这会将数据表的元数据传递到一个方便的矩阵中,我们可以从 C# 访问该矩阵,这是我的用例的一部分。

但是,FillSchema() 会清除存储过程参数值。在我的代码中,我试图在调用 FillSchema 后收集存储过程的输出参数值,这就是我目睹的原因。我找不到关于这一点的任何文档。

如果您的代码看起来像这样,它将起作用。

    da.Fill(ds);

    var returnVal = returnParam.Value; // value as expected

    da.FillSchema(ds, SchemaType.Source);

如果您的代码看起来像这样,它将无法正常工作

    da.Fill(ds);

    da.FillSchema(ds, SchemaType.Source);

    var returnVal = returnParam.Value; // value reset by prev line !!!!

标签: c#sql-serversqldataadapter

解决方案


是的你可以。

Create PROCEDURE TestSP
    @test varchar(max) output
AS
BEGIN
    select @test = 'abc'
    select top 10 * from MyTable
    return 4

END




using (SqlConnection connection = new SqlConnection(conString))
        {
            connection.Open();

            SqlCommand cmd = new SqlCommand("TestSP", connection);
            cmd.CommandType = CommandType.StoredProcedure;

            SqlParameter param = new SqlParameter("@test", SqlDbType.VarChar, -1);
            param.Direction = ParameterDirection.Output;

            var returnParam = cmd.Parameters.Add("@Return", SqlDbType.Int);
            returnParam.Direction = ParameterDirection.ReturnValue;

            cmd.Parameters.Add(param);

            SqlDataAdapter da = new SqlDataAdapter(cmd);
            DataSet ds = new DataSet();
            da.Fill(ds);

            var returnVal = returnParam.Value; //4
            var output = param.Value; // abc
            var data = ds.Tables[0].Rows[0][0];  //data from my table
        }

推荐阅读