OracleCommand StoredProcedure 返回 "null" 而不是 DBNull

OracleCommand StoredProcedure returning "null" instead of DBNull

我有一个存储过程,在某些情况下 returns 为空。当我 ToString() 空值时,它 returns "null" 作为字符串而不是空字符串,但是如果我不使用 .ToString() 方法,它会导致错误。

Public Function ReturnValue(ByVal lngId As Long) As String
    Dim adoCmd As New OracleCommand
    Dim strReturn As String = ""

    With adoCmd

        .CommandText = "BUS_TEST.ReturnValue"
        .CommandType = CommandType.StoredProcedure

        .Parameters.Add("return", OracleDbType.Char, 256, strReturn, ParameterDirection.ReturnValue)
        .Parameters.Add("lngId", OracleDbType.Double, lngId, ParameterDirection.Input)
    End With

    objSalUtil.ExecFunc(ocEWBConnection, adoCmd, "ReturnValue")

    Return adoCmd.Parameters(0).Value.ToString

End Function

以上代码returns"null"

Public Function ReturnValue(ByVal lngId As Long) As String
    Dim adoCmd As New OracleCommand
    Dim strReturn As String = ""

    With adoCmd

        .CommandText = "BUS_TEST.ReturnValue"
        .CommandType = CommandType.StoredProcedure

        .Parameters.Add("return", OracleDbType.Char, 256, strReturn, ParameterDirection.ReturnValue)
        .Parameters.Add("lngId", OracleDbType.Double, lngId, ParameterDirection.Input)
    End With

    objSalUtil.ExecFunc(ocEWBConnection, adoCmd, "ReturnValue")

    Return adoCmd.Parameters(0).Value

End Function

以上代码导致 InvalidCastException:从类型 'OracleString' 到类型 'String' 的转换无效。

Public Function ReturnValue(ByVal lngId As Long) As String
    Dim adoCmd As New OracleCommand
    Dim strReturn As String = ""

    With adoCmd

        .CommandText = "BUS_TEST.ReturnValue"
        .CommandType = CommandType.StoredProcedure

        .Parameters.Add("return", OracleDbType.Char, 256, strReturn, ParameterDirection.ReturnValue)
        .Parameters.Add("lngId", OracleDbType.Double, lngId, ParameterDirection.Input)
    End With

    objSalUtil.ExecFunc(ocEWBConnection, adoCmd, "ReturnValue")

    Return strReturn

End Function

最后,上面的代码 returns 是一个正确的空字符串,但它在所有情况下都是如此,无论是否应该返回某些内容。

我过去经常使用这样的存储过程,但是在所有情况下它们总是返回一个值。我不太确定如何处理这个空值。我不想先检查包含 "null" 的字符串,因为这有点老套,而且我想知道我做错了什么。

原来在两个参数之间添加这一行解决了问题。

adoCmd.Parameters(0).DbType = DbType.String

我认为,您正在使用 ODP.NET。在这种情况下,而不是 this

Return adoCmd.Parameters(0).Value

你这样做

Dim oraStr As OracleString = CType(adoCmd.Parameters(0).Value, OracleString)
Return oraStr.Value ' return .net string

发生的事情是,这个 adoCmd.Parameters(0).Value return 是你 Oracle null。如果您将 return 值转换为 Oracle 类型,现在您可以访问 .Net 类型的值。当您使用 adoCmd.Parameters(0).Value.ToString() 时,您会得到 ToString 的 Oracle 实现,它只是 return 一些词 null

当您使用 odp.net Oracle 参数、存储过程或具有 return 值的参数化查询时,请记住这一点 - 没关系,就像这里

Dim sql as String = "insert into table ...) returning fld1 into :1"

Interesting Observation: In SqlClient this is illegal Parameters(0).Value = Nothing. It wants DBNull.Value. In ODP.NET is not a problem. It takes any - Nothing or/and DBNull.Value

当您使用 OracleReader 时,尤其是通过 IDataReader - 这不是问题。 Reader("fld1") 将 return .net 类型。

Dim r As IdataReader = cmd.ExecuteReader...
Dim i As Integer = reader("fld1")

您需要注意的是将 Oracle 数据库类型与 .NET 相匹配。问题是,它们不匹配。如果您声明 table 字段 Number(9) 它将 return .net IntegerNumber(9) 不够大以适应 Integer.MaxValue。如果声明 table 字段 Number(10)Reader("fld1") 将 return Long。因此,.net Integer 介于 Number(9)Number(10) 之间。你需要使用 convert

 Dim i As Integer = convert.ToInt32(reader("fld1"))