调用CLR存储过程时遇nvarchar转int错误,求解决方案
首先,你遇到的转换错误根源在VB.NET代码中添加输出参数的方式错误,而SSMS里看到的int返回值是CLR存储过程的默认执行状态,和你的输出参数完全是两回事,我来一步步拆解:
1. 核心错误:输出参数的类型定义错误
看你VB代码里这一行:
cmd.Parameters.AddWithValue("@Result", SqlDbType.NVarChar )
AddWithValue的第二个参数是参数的初始值,但你这里传的是SqlDbType.NVarChar——这是一个枚举值,对应int类型(SqlDbType.NVarChar的枚举值是23)。这就导致SQL Server错误地认为@Result是int类型,但你的CLR存储过程定义里@Result是SqlString(对应nvarchar类型),所以当存储过程试图把nvarchar结果赋值给这个被标记为int的参数时,就抛出了Error converting data type nvarchar to int的错误。
修复方法:正确定义输出参数
不要用AddWithValue来指定输出参数的类型,应该用Add方法明确指定参数名、类型和长度,再设置参数方向:
替换原来的输出参数添加代码:
' 改用Add方法指定类型和长度,匹配你SSMS里定义的nvarchar(50) cmd.Parameters.Add("@Result", SqlDbType.NVarChar, 50) cmd.Parameters("@Result").Direction = ParameterDirection.Output
这样就明确告诉SQL Server@Result是nvarchar类型,和CLR存储过程的参数类型完全匹配,转换错误就会消失。
2. 关于SSMS里的int返回值
你在SSMS执行时看到的@return_value是int类型,这是SQL Server对无返回值的CLR存储过程的默认行为:你的CLR存储过程是void返回(代码里public static void SqlStoredProcedure1),SQL Server会自动返回0作为执行状态码(int类型),这个值只是标识存储过程是否正常执行(正常返回0,出错时返回错误码),和你的@Result输出参数没有关系。
额外优化建议
- 你的VB代码里重复设置了
cmd.CommandText = "GetDistanceAndTime",其实前面New SqlCommand("GetDistanceAndTime", CN)已经指定了,这行可以删掉。 - 建议用
Using语句管理SqlConnection和SqlCommand,确保资源自动释放,避免内存泄漏:
Try Using CN As New SqlConnection(My.Settings.myConnection) CN.Open() Dim Profile As String = "40T" Dim StartPosition As String = "53.6924582,-2.8730636000" Dim Destination As String = "46.18186,1.380222" Dim RetValue As String = "Testvalue" Using cmd As New SqlCommand("GetDistanceAndTime", CN) cmd.CommandType = CommandType.StoredProcedure cmd.Parameters.AddWithValue("@Profile", Profile) cmd.Parameters.AddWithValue("@StartPosition", StartPosition) cmd.Parameters.AddWithValue("@Destination", Destination) ' 正确添加输出参数 cmd.Parameters.Add("@Result", SqlDbType.NVarChar, 50).Direction = ParameterDirection.Output Try cmd.ExecuteNonQuery() RetValue = cmd.Parameters("@Result").Value.ToString() If RetValue.Length > 2 Then ' 这里可以添加你的业务逻辑 End If Catch ex As Exception MessageBox.Show(ex.Message) End Try End Using End Using Catch ex As Exception MessageBox.Show(ex.Message) End Try
这样修改后,转换错误应该就能解决,同时代码的资源管理更规范。
内容的提问来源于stack exchange,提问作者joebohen

