简体   繁体   中英

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

I created a SQL Server database project (VS2017) and I added a SQLCLR C# stored procedure. It's declared like this:

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

I also have a Windows Forms application that connects to the database and I try to execute this procedure like this:

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;

There's a problem with declared data type though. What is the correct way of declaring data types for SQLCLR stored procedures or getting its output parameter values?

  1. Rather than using .NET types for input/output parameter types of SQLCLR objects, use the Sql* types, such as SqlString , SqlInt32 , etc. All of them have a Value property that returns the expected .NET type. For example, SqlString.Value returns a string , SqlInt32.Value returns an int , and so on.
  2. If the input can ever be NULL , you can test for that by checking the IsNull boolean property that all of the Sql* types have.
  3. The appropriate replacement type for a byte[] is SqlBytes . And SqlBytes.Value will return a byte[] .
  4. Even if not necessary, is probably best to decorate the method destined to be the SQLCLR stored procedure with: [SqlProcedure()] .
  5. Putting the recommendations noted above together, we get:

     [SqlProcedure()] public static void RequestServiceToEncryptPassword(SqlBytes param1, out SqlInt32 param2, out SqlBytes param3) { if(.param1.IsNull) { param2 = doSomethingWithByteArray(param1;Value). }... more.... }
  6. For the parameters, it is best to not use AddWithValue (as mentioned by Çöđěxěŕ in a comment on the question) as it can sometimes have problems, especially with variable length types (ie strings and binaries such as VARCHAR , VARBINARY , etc).
  7. For the parameters, I prefer to create each parameter as an object, which makes it easy to interact with (and more readable for more maintainable code):

     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);

    Please note that the optional size parameter of the SqlParameter constructor (ie the 500 for param1 ):

    1. should always be set for variable length types
    2. can be set to SqlMetaData.Max (which simply returns -1 ) for the MAX types
    3. should match the length declared for its associated paramter in the stored procedure (or user-defined function), which yes, also needs to have an explicitly declared length (you don't want to rely on the default as it's not the same value in all contexts)
  8. After executing the SqlCommand , and output parameters will have their values set, and those can be accessed by reading their Value property. This value will likely need to be casted into a .NET type:

     int returnVal = (int)paramParam2.Value;
  9. If it's possible for an output parameter to be set to NULL , then you need to check for DbNull.Value before casting it to the appropriate type.

For more info on working with SQLCLR in general, please visit: SQLCLR Info

You have to map the parameters to the SqlDbType enum, on System.Data . So an int would map to SqlDbType.Int for example. For the output parameters, you can get the values using for example:

sqlCommand.Parameters("param2").Value
sqlCommand.Parameters("param3").Value

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM