如何获取SQLCLR存储过程的输出参数值?

How to get output parameter values of a SQLCLR stored procedure?

我创建了一个 SQL 服务器数据库项目 (VS2017) 并添加了一个 SQLCLR C# 存储过程。它是这样声明的:

public static void RequestServiceToEncryptPassword(byte[] param1, out int param2, out byte[] param3)

我还有一个连接到数据库的 Windows Forms 应用程序,我尝试像这样执行此过程:

sqlCommand = new SqlCommand(procName, sqlConnection);
sqlCommand.CommandType = System.Data.CommandType.StoredProcedure;

sqlCommand.Parameters.AddWithValue("param1", param1).Direction = System.Data.ParameterDirection.Input;
sqlCommand.Parameters.AddWithValue("param2", int).Direction = System.Data.ParameterDirection.Output;
sqlCommand.Parameters.AddWithValue("param3", byte[]).Direction = System.Data.ParameterDirection.Output;

虽然声明的数据类型有问题。为 SQLCLR 存储过程声明数据类型或获取其输出参数值的正确方法是什么?

  1. SQLCLR 对象的 input/output 参数类型不使用 .NET 类型,而是使用 Sql* 类型,例如 SqlStringSqlInt32 等。所有他们有一个 Value 属性,return 是预期的 .NET 类型。例如,SqlString.Value return 一个 stringSqlInt32.Value return 一个 int,等等。
  2. 如果输入可以是 NULL,您可以通过检查所有 Sql* 类型都具有的 IsNull 布尔值 属性 来测试它。
  3. byte[] 的适当替换类型是 SqlBytesSqlBytes.Value 将 return 变成 byte[].
  4. 即使没有必要,最好用以下方式装饰注定要成为SQLCLR存储过程的方法:[SqlProcedure()].
  5. 综合上述建议,我们得到:

    [SqlProcedure()]
    public static void  RequestServiceToEncryptPassword(SqlBytes param1,
         out SqlInt32 param2, out SqlBytes param3)
    {
      if(!param1.IsNull)
      {
         param2 = doSomethingWithByteArray(param1.Value);
      }
    
      ... more ....
    }
    
  6. 对于参数,最好不要使用AddWithValue(正如Çöđěxěŕ在对问题的评论中提到的)因为它有时会出现问题,特别是具有可变长度类型(即字符串和二进制文件,例如 VARCHARVARBINARY 等)。
  7. 对于参数,我更喜欢将每个参数创建为一个对象,这样可以更轻松地与之交互(对于更可维护的代码,可读性更高):

    paramParam1 = new SqlParameter("param1", SqlDbType.VarBinary, 500);
    // paramParam1.Direction = ParameterDirection.Input; // Input is default / assumed
    paramParam1.Value = param1;
    sqlCommand.Parameters.Add(paramParam1);
    
    paramParam2 = new SqlParameter("param2", SqlDbType.Int);
    paramParam2.Direction = ParameterDirection.Output;
    paramParam2.Value = intVariable;
    sqlCommand.Parameters.Add(paramParam2);
    

    请注意 SqlParameter 构造函数的可选大小参数(即 param1500):

    1. 应该总是设置为可变长度类型
    2. 对于 MAX 类型 ,
    3. 可以设置为 SqlMetaData.Max(即 returns -1
    4. 应该匹配在存储过程(或用户定义的函数)中为其关联参数声明的长度,是的,还需要有一个明确声明的长度(你不想依赖默认值,因为它是在所有情况下都不是相同的值)
  8. 执行 SqlCommand 后,输出参数将设置它们的值,可以通过读取它们的 Value 属性 来访问这些值。此值可能需要转换为 .NET 类型:

    int returnVal = (int)paramParam2.Value;
    
  9. 如果可以将输出参数设置为 NULL,那么您需要在将其转换为适当的类型之前检查 DbNull.Value

有关一般使用 SQLCLR 的更多信息,请访问:SQLCLR Info