如何获取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 存储过程声明数据类型或获取其输出参数值的正确方法是什么?
- SQLCLR 对象的 input/output 参数类型不使用 .NET 类型,而是使用
Sql*
类型,例如 SqlString
、SqlInt32
等。所有他们有一个 Value
属性,return 是预期的 .NET 类型。例如,SqlString.Value
return 一个 string
,SqlInt32.Value
return 一个 int
,等等。
- 如果输入可以是
NULL
,您可以通过检查所有 Sql*
类型都具有的 IsNull
布尔值 属性 来测试它。
byte[]
的适当替换类型是 SqlBytes
。 SqlBytes.Value
将 return 变成 byte[]
.
- 即使没有必要,最好用以下方式装饰注定要成为SQLCLR存储过程的方法:
[SqlProcedure()]
.
综合上述建议,我们得到:
[SqlProcedure()]
public static void RequestServiceToEncryptPassword(SqlBytes param1,
out SqlInt32 param2, out SqlBytes param3)
{
if(!param1.IsNull)
{
param2 = doSomethingWithByteArray(param1.Value);
}
... more ....
}
- 对于参数,最好不要使用
AddWithValue
(正如Çöđěxěŕ在对问题的评论中提到的)因为它有时会出现问题,特别是具有可变长度类型(即字符串和二进制文件,例如 VARCHAR
、VARBINARY
等)。
对于参数,我更喜欢将每个参数创建为一个对象,这样可以更轻松地与之交互(对于更可维护的代码,可读性更高):
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
构造函数的可选大小参数(即 param1
的 500
):
- 应该总是设置为可变长度类型
对于 MAX
类型
,- 可以设置为
SqlMetaData.Max
(即 returns -1
)
- 应该匹配在存储过程(或用户定义的函数)中为其关联参数声明的长度,是的,还需要有一个明确声明的长度(你不想依赖默认值,因为它是在所有情况下都不是相同的值)
执行 SqlCommand
后,输出参数将设置它们的值,可以通过读取它们的 Value
属性 来访问这些值。此值可能需要转换为 .NET 类型:
int returnVal = (int)paramParam2.Value;
如果可以将输出参数设置为 NULL
,那么您需要在将其转换为适当的类型之前检查 DbNull.Value
。
有关一般使用 SQLCLR 的更多信息,请访问:SQLCLR Info
我创建了一个 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 存储过程声明数据类型或获取其输出参数值的正确方法是什么?
- SQLCLR 对象的 input/output 参数类型不使用 .NET 类型,而是使用
Sql*
类型,例如SqlString
、SqlInt32
等。所有他们有一个Value
属性,return 是预期的 .NET 类型。例如,SqlString.Value
return 一个string
,SqlInt32.Value
return 一个int
,等等。 - 如果输入可以是
NULL
,您可以通过检查所有Sql*
类型都具有的IsNull
布尔值 属性 来测试它。 byte[]
的适当替换类型是SqlBytes
。SqlBytes.Value
将 return 变成byte[]
.- 即使没有必要,最好用以下方式装饰注定要成为SQLCLR存储过程的方法:
[SqlProcedure()]
. 综合上述建议,我们得到:
[SqlProcedure()] public static void RequestServiceToEncryptPassword(SqlBytes param1, out SqlInt32 param2, out SqlBytes param3) { if(!param1.IsNull) { param2 = doSomethingWithByteArray(param1.Value); } ... more .... }
- 对于参数,最好不要使用
AddWithValue
(正如Çöđěxěŕ在对问题的评论中提到的)因为它有时会出现问题,特别是具有可变长度类型(即字符串和二进制文件,例如VARCHAR
、VARBINARY
等)。 对于参数,我更喜欢将每个参数创建为一个对象,这样可以更轻松地与之交互(对于更可维护的代码,可读性更高):
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
构造函数的可选大小参数(即param1
的500
):- 应该总是设置为可变长度类型 对于
MAX
类型 ,- 可以设置为
SqlMetaData.Max
(即 returns-1
) - 应该匹配在存储过程(或用户定义的函数)中为其关联参数声明的长度,是的,还需要有一个明确声明的长度(你不想依赖默认值,因为它是在所有情况下都不是相同的值)
执行 SqlCommand
后,输出参数将设置它们的值,可以通过读取它们的 Value
属性 来访问这些值。此值可能需要转换为 .NET 类型:
int returnVal = (int)paramParam2.Value;
NULL
,那么您需要在将其转换为适当的类型之前检查 DbNull.Value
。有关一般使用 SQLCLR 的更多信息,请访问:SQLCLR Info