【问题标题】:How do you Send More that 20 Parameters to a Stored Procedure Using ODP.Net?如何使用 ODP.Net 向存储过程发送超过 20 个参数?
【发布时间】:2010-04-28 18:02:58
【问题描述】:

从 Microsoft 的 Oracle 驱动程序切换到 ODP.NET 版本 10.2.0.100。在过程中将数据类型更改为 OracleDBTypes 后,该过程使用 System.Data.OracleClient 完美运行,如果我们尝试传入超过 20 个参数,该过程将失败。返回的错误是:

ORA-06550:第 1 行,第 7 列:PLS-00306:调用“ADD_TARP_EVENT”时参数的数量或类型错误 ORA-06550:第 1 行,第 7 列:PL/SQL:语句被忽略e

如果我们将参数数量减少到少于 20 个,它就可以工作。这是一个已知的问题?

这里是创建参数的代码:

    Shared Function CreateTarpEventCommand(ByVal aTarpEvent As TARPEventType) As OracleCommand
    Dim cmd As New OracleCommand

    With aTarpEvent

        cmd.Parameters.Add(New OracleParameter("I_facID_C", OracleDbType.Char)).Value = .FacilityShortName
        cmd.Parameters.Add(New OracleParameter("I_facName_VC", OracleDbType.Varchar2)).Value = .FacilityLongName
        cmd.Parameters.Add(New OracleParameter("I_client_VC", OracleDbType.Varchar2)).Value = .ComputerNameTarpIsRunningOn
        cmd.Parameters.Add(New OracleParameter("I_TARP_Version_VC", OracleDbType.Varchar2)).Value = .TarpVersionNumber
        cmd.Parameters.Add(New OracleParameter("I_NAS_Type_VC", OracleDbType.Varchar2)).Value = .FacilityNASSystemType
        cmd.Parameters.Add(New OracleParameter("I_Aircraft1_Callsign_VC", OracleDbType.Varchar2)).Value = .Aircraft1Callsign

        If .Aircraft1Type Is Nothing Then
            cmd.Parameters.Add(New OracleParameter("I_Aircraft1_Type_VC", OracleDbType.Varchar2)).Value = .Aircraft1Type
        End If

        If .Aircraft1Category Is Nothing Then
            cmd.Parameters.Add(New OracleParameter("I_Aircraft1_Cat_VC", OracleDbType.Varchar2)).Value = .Aircraft1Category
        End If

        cmd.Parameters.Add(New OracleParameter("I_Aircraft2_Callsign_VC", OracleDbType.Varchar2)).Value = .Aircraft2Callsign

        If .Aircraft2Type Is Nothing Then
            cmd.Parameters.Add(New OracleParameter("I_Aircraft2_Type_VC", OracleDbType.Varchar2)).Value = .Aircraft2Type
        End If

        If .Aircraft2Category Is Nothing Then
            cmd.Parameters.Add(New OracleParameter("I_Aircraft2_Cat_VC", OracleDbType.Varchar2)).Value = .Aircraft2Category
        End If

        If .SensorShortName Is Nothing Then
            cmd.Parameters.Add(New OracleParameter("I_Sensor_Name_VC", OracleDbType.Varchar2)).Value = .SensorShortName
        End If


        If .TarpConfigurationName Is Nothing Then
            cmd.Parameters.Add(New OracleParameter("I_TARP_Config_Name_VC", OracleDbType.Varchar2)).Value = .TarpConfigurationName
        End If

        If .EntryCreatorID Is Nothing Then
            cmd.Parameters.Add(New OracleParameter("I_Create_VC", OracleDbType.Varchar2)).Value = .EntryCreatorID
        End If

        If .LogAction Is Nothing Then
            cmd.Parameters.Add(New OracleParameter("I_Log_Action_VC", OracleDbType.Varchar2)).Value = .LogAction
        End If

        cmd.Parameters.Add(New OracleParameter("I_TARP_Mode_VC", OracleDbType.Varchar2)).Value = .TarpOperatingMode
        cmd.Parameters.Add(New OracleParameter("I_Min_Loss_N", OracleDbType.Decimal)).Value = .ClosestMeasureOfLoSS

        If .MapName Is Nothing Then
            cmd.Parameters.Add(New OracleParameter("I_MAP_NAME_VC", OracleDbType.Varchar2)).Value = .MapName
        End If

        If .TarpConfigurationFileHash Is Nothing Then
            cmd.Parameters.Add(New OracleParameter("I_CONFIG_HASH_VC", OracleDbType.Varchar2)).Value = .TarpConfigurationFileHash
        End If

        Dim aDate As OracleDate = CType(.LossEventsMessages(0).LossEventTime, System.DateTime)
        cmd.Parameters.Add(New OracleParameter("I_FIRST_LOSS_EVENT_DATE", OracleDbType.Date)).Value = aDate
        cmd.Parameters.Add(New OracleParameter("I_FIRST_LOSS_EVENT_MS_N", OracleDbType.Int32)).Value = .LossEventsMessages(0).LossEventMilliSeconds

        If .ZippedMapFiles Is Nothing Then
            cmd.Parameters.Add(New OracleParameter("I_Map_File_BL", OracleDbType.Blob)).Value = .ZippedMapFiles
        End If

        cmd.Parameters.Add(New OracleParameter("I_TARP_Package_BL", OracleDbType.Blob)).Value = .ZippedTarpPackageWithoutMaps

        cmd.Parameters.Add(New OracleParameter("rs_RESULTS", OracleDbType.RefCursor)).Direction = ParameterDirection.Output

    End With
    Return cmd
End Function

这是执行该过程的代码:

 Dim workingDataSet As New DataSet
    Dim oracleConnection As New OracleConnection
    Dim cmd As New OracleCommand
    Dim oracleDataAdapter As New OracleDataAdapter

    Try

         Using oracleConnection
            oracleConnection.ConnectionString = System.Configuration.ConfigurationManager.AppSettings("MasterConnectionODT")
            cmd = HelperDB.CreateTarpEventCommand(TarpEvent)

            cmd.Connection = oracleConnection
            cmd.CommandText = "LOADER.ADD_TARP_EVENT"
            cmd.CommandType = CommandType.StoredProcedure

            Using oracleConnection
                oracleConnection.Open()
                Dim aTransation As OracleTransaction = oracleConnection.BeginTransaction(IsolationLevel.ReadCommitted)
                Try
                    Using oracleDataAdapter
                        oracleDataAdapter = New OracleDataAdapter(cmd)
                        oracleDataAdapter.TableMappings.Add("Results", "rs_Max")
                        oracleDataAdapter.Fill(workingDataSet)

....

【问题讨论】:

  • ODP.NET 的一些旧版本存在可怕的错误和不稳定。您是否可以尝试当前版本以查看问题是否消失?切换到 11.1.0.7.20 后,我对 ODP.NET 感到更加满意。
  • 有源代码的最终解决方案吗?

标签: .net vb.net oracle odt.net


【解决方案1】:

这让我感到惊讶,因为 20 并不是一个很高的数字,我认为您更有可能混淆了一些参数(当超过 20 个时很容易做到)。

但要尝试一下,我建议创建一个包含 21 个参数的过程,所有参数都是数字,然后将 1 发送给所有参数,这样您就可以确保它不仅仅是输入错误。

【讨论】:

    【解决方案2】:

    有两种调用 oracle 过程的方法。第一个是命名符号

    proc (p_1 => 'test', p2 => 1);
    

    第二个是位置

    proc ('test', 1);
    

    在命名表示法中,您可以按任意顺序放置参数并省略任何使用 DEFAULT 定义的参数。在位置表示法中,它们必须按照定义的顺序排列,只有最后一个可以省略。也就是说,如果您提供五个参数并且该过程定义了六个,那么它假定缺少的一个是第六个。同样,第六个必须有一个默认值。输出参数不能有默认值,必须提供。

    我不确定 ODP 如何工作以选择使用哪个(尽管可以通过使用 DBMS_MONITOR 跟踪会话并查看生成的跟踪文件来确认)。

    无论如何,请检查参数名称是否与代码中的名称匹配。除非引用,否则 Oracle 将标识符视为大写。此外,如果任何参数没有 DEFAULT,则必须在调用中设置它们(即使设置为 null)。

    【讨论】:

      【解决方案3】:

      存储过程“LOADER.ADD_TARP_EVENT”将过程参数值默认为 Null(如果适用于服务器端)。当我们构建 ADO Oracle 命令时,我们没有填充 Null 参数,因为它们已经在过程中设置为默认为 Null。这与 ADO.NET 配合得很好。 ODT 显然要求将值作为 dbNull 传入。一旦我们传入 dbNull 值,所有值都按预期工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-11-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多