Reputation: 91
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?
Upvotes: 0
Views: 1753
Reputation: 48914
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.NULL
, you can test for that by checking the IsNull
boolean property that all of the Sql*
types have.byte[]
is SqlBytes
. And SqlBytes.Value
will return a byte[]
.[SqlProcedure()]
.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 ....
}
AddWithValue
(as mentioned by Çöđěxěŕ in a comment on the question) as it can sometimes have problems, especially with variable length types (i.e. strings and binaries such as VARCHAR
, VARBINARY
, etc).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 (i.e. the 500
for param1
):
SqlMetaData.Max
(which simply returns -1
) for the MAX
typesAfter 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;
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
Upvotes: 2