[英]How to use an Oracle Ref Cursor from C# ODP.NET as a ReturnValue Parameter, without using a Stored Function or Procedure?
[英]How do you Send More that 20 Parameters to a Stored Procedure Using ODP.Net?
從Microsoft的Oracle驅動程序切換到ODP.NET版本10.2.0.100。 在使用System.Data.OracleClient正常運行的過程中將數據類型更改為OracleDBTypes之后,如果嘗試傳遞20個以上的參數,則過程將失敗。 返回的錯誤是:
ORA-06550:第1行,第7列:PLS-00306:調用“ ADD_TARP_EVENT”時參數的數量或類型錯誤ORA-06550:第1行,第7列:PL / SQL:語句被忽略
如果我們將參數數量減少到少於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)
....
因為20的數字不是一個很高的數字,這會讓我感到驚訝,我認為您更有可能混入一些參數(當超過20個時,很容易做到)。
但是要嘗試一下,我建議創建一個包含21個參數的過程,所有參數均為數字,然后將1發送給所有參數,這樣就可以確保它不僅是一個錯誤的類型。
有兩種方法可以調用oracle過程。 第一個是命名法
proc (p_1 => 'test', p2 => 1);
第二個是位置
proc ('test', 1);
在命名符號中,您可以按任何順序放置參數,並忽略使用DEFAULT定義的任何參數。 在位置表示法中,它們必須按照定義的順序,並且只能省略最后一個。 也就是說,如果您提供五個參數,並且該過程定義了六個,則假定缺少的一個是第六個。 同樣,第六個必須具有默認值。 輸出參數不能具有默認值,必須提供。
我不確定ODP如何選擇使用哪個(盡管可以通過使用DBMS_MONITOR跟蹤會話並查看生成的跟蹤文件來確認)。
無論如何,請檢查參數名稱是否與代碼中的名稱匹配。 除非加引號,否則Oracle將標識符視為大寫。 另外,如果任何參數沒有默認值,則必須在調用中進行設置(即使設置為null)。
存儲過程“ LOADER.ADD_TARP_EVENT”在服務器端適用的情況下,將過程參數值默認為Null。 在構建ADO Oracle Command時,我們沒有填充Null參數,因為在該過程中已經將它們設置為默認值。 這對於ADO.NET效果很好。 ODT顯然要求將值作為dbNull傳入。 一旦我們為所有值傳遞dbNull,它們都將按預期工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.