简体   繁体   English

如何使用ODP.Net向存储过程发送20多个参数?

[英]How do you Send More that 20 Parameters to a Stored Procedure Using ODP.Net?

Switching from Microsofts Oracle Driver to ODP.NET version 10.2.0.100. 从Microsoft的Oracle驱动程序切换到ODP.NET版本10.2.0.100。 After changing the data types to OracleDBTypes in a procedure, that worked perficetly using System.Data.OracleClient, the procedure fails if we try and pass in more that 20 parameters. 在使用System.Data.OracleClient正常运行的过程中将数据类型更改为OracleDBTypes之后,如果尝试传递20个以上的参数,则过程将失败。 The error returned is: 返回的错误是:

ORA-06550: line 1, column 7: PLS-00306: wrong number or types of arguments in call to 'ADD_TARP_EVENT' ORA-06550: line 1, column 7: PL/SQL: Statement ignorede ORA-06550:第1行,第7列:PLS-00306:调用“ ADD_TARP_EVENT”时参数的数量或类型错误ORA-06550:第1行,第7列:PL / SQL:语句被忽略

If we reduce the number of parameters to less than 20 it works. 如果我们将参数数量减少到少于20个,它将起作用。 Is this a known issue? 这是一个已知的问题?

Here the code for creating the parameters: 下面是用于创建参数的代码:

    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

And here is the code for executing the procedure: 这是执行该过程的代码:

 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)

.... ....

It would surprise me since 20 isn't such a high number, I'd think it's more likely that you're getting some parameter mixed up (easy enough to do when it's over 20 of them). 因为20的数字不是一个很高的数字,这会让我感到惊讶,我认为您更有可能混入一些参数(当超过20个时,很容易做到)。

But to try it out I suggest creating a procedure with 21 parameters, all being Numbers and then sending in 1 to all of them, that way you could make sure that it's not just a mistype. 但是要尝试一下,我建议创建一个包含21个参数的过程,所有参数均为数字,然后将1发送给所有参数,这样就可以确保它不仅是一个错误的类型。

There are two ways of calling oracle procedures. 有两种方法可以调用oracle过程。 The first is named notation 第一个是命名法

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

The second is positional 第二个是位置

proc ('test', 1);

In named notation, you can put the parameters in any order and omit any that are defined with a DEFAULT. 在命名符号中,您可以按任何顺序放置参数,并忽略使用DEFAULT定义的任何参数。 In positional notation, they must be in the order they are defined in and only the last ones can be omitted. 在位置表示法中,它们必须按照定义的顺序,并且只能省略最后一个。 That is, if you supply five parameters and the procedure has six defined, then it assumes the missing one is the sixth. 也就是说,如果您提供五个参数,并且该过程定义了六个,则假定缺少的一个是第六个。 Again, the sixth must have a DEFAULT. 同样,第六个必须具有默认值。 An output parameter cannot have a default and must be supplied. 输出参数不能具有默认值,必须提供。

I'm not sure how ODP works to choose which to use (though it could be confirmed by tracing the session using DBMS_MONITOR and looking at the resultant trace file). 我不确定ODP如何选择使用哪个(尽管可以通过使用DBMS_MONITOR跟踪会话并查看生成的跟踪文件来确认)。

Anyway, check that the names of the parameters match those in your code. 无论如何,请检查参数名称是否与代码中的名称匹配。 Oracle treats identifiers as uppercase unless quoted. 除非加引号,否则Oracle将标识符视为大写。 Also, if any parameters do not have a DEFAULT, they MUST be set in the call (even if set to null). 另外,如果任何参数没有默认值,则必须在调用中进行设置(即使设置为null)。

The stored procedure "LOADER.ADD_TARP_EVENT" defaulted the procedure parameter values to Null where applicable on the server side. 存储过程“ LOADER.ADD_TARP_EVENT”在服务器端适用的情况下,将过程参数值默认为Null。 When we built the ADO Oracle Command we did not populate the Null parameters, as they were already set to default to Null in the procedure. 在构建ADO Oracle Command时,我们没有填充Null参数,因为在该过程中已经将它们设置为默认值。 This worked great with ADO.NET. 这对于ADO.NET效果很好。 ODT aparently requires that the values be passed in as dbNull. ODT显然要求将值作为dbNull传入。 Once we passed in dbNull for the values all worked as expected. 一旦我们为所有值传递dbNull,它们都将按预期工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM