ExecuteScalar returns 存储过程中没有任何内容

ExecuteScalar returns nothing from stored procedure

我有一个简单的存储过程,它 returns type_id (int) 作为 OUTPUT 参数使用 type_name (varchar(100)) 作为输入参数。当我在 SqlServer 中执行存储过程时,它工作正常并且 returns 适当的 type_id.

CREATE PROCEDURE [dbo].[intake_types_select_by_type_name]
    @type_name varchar(100),
    @type_id integer OUTPUT
AS
BEGIN
    SET NOCOUNT ON;
    SET XACT_ABORT ON

    SELECT  @type_id = type_id
    FROM    intake_types
    WHERE   type_name = @type_name
END

但是,当我从 VisualStudio 中的函数调用存储过程时,参数 @type_id returns Nothing.

Public Shared Function sp_intake_types_select_by_type_name(ByVal conn As DBConnection, ByVal caseName As String) As Integer
    Dim sp As SqlCommand = conn.GetStoredProcedure("intake_types_select_by_type_name")
    With sp.Parameters
        .Add("@type_name", SqlDbType.VarChar, ParameterDirection.Input).Value = caseName
        .Add("@type_id", SqlDbType.Int)
        .Item("@type_id").Direction = ParameterDirection.Output
    End With
    sp.ExecuteScalar()
    If Not IsDBNull(sp.Parameters("@type_id").Value) Then
        Return sp.Parameters("@type_id").Value
    Else
        Return Nothing
    End If
End Function

我花了几个小时在网上搜索解决方案,但没有找到任何帮助。我在另一个项目中有一个类似的存储过程和函数,它使用相同的编码和逻辑并且工作正常(但是它 returns a varchar 作为 OUTPUT 参数)。我比较了这两个项目,看看我是否缺少一些简单但没有乐趣的东西。

您确实应该使用 Option Strict On 并更正它指出的问题。目前,正在执行数据类型之间的隐式转换,这会使您的代码变慢,并且可能 error-prone.

我建议如下:

CREATE PROCEDURE [dbo].[intake_types_select_by_type_name]
    @type_name varchar(100)
AS
BEGIN
    SET NOCOUNT ON;
    SET XACT_ABORT ON;

    SELECT  type_id
    FROM    intake_types
    WHERE   type_name = @type_name
END

以及调用它的函数:

Option Strict On
' ....'

Public Shared Function sp_intake_types_select_by_type_name(ByVal conn As DBConnection, ByVal caseName As String) As Integer
    Dim sp As SqlCommand = conn.GetStoredProcedure("intake_types_select_by_type_name")
    sp.Parameters.Add("@type_name", SqlDbType.VarChar, 100).Value = caseName

    Dim result As Object = sp.ExecuteScalar()

    If result Is Nothing Then
        Return -1 ' check for -1 in the calling code '
    Else
        Return CInt(result)
    End If

End Function

指定 SQL 参数的大小几乎总是一个好主意,这样数据库就可以 re-use 执行计划,而不是为每个参数长度制定一个新的执行计划。

请注意,对所有内容都使用一个 SQL 连接通常不是一个好主意:您应该先使用该连接,然后在立即使用完后立即将其处理掉。起初这似乎是个好主意,但它违背了它的设计方式(connection pooling 处理快速 re-opening 的连接)。

参考:Execute Scalar to trap error in case of no records returned.