Reputation: 3965
We are using an Oracle stored procedure in a C# program, which was working fine until we added the 'v_nameurn' variable.
Here's the Oracle procedure:
create or replace procedure stats_By_Date (
v_SDate IN varchar2,
v_EDate IN varchar2,
v_user IN number,
v_nameurn IN number,
p_cursor OUT SYS_REFCURSOR
) as
BEGIN
OPEN p_cursor FOR
select T1.Staff_No,
T3.Title,
T2.Verno,
To_char(T1.Response_dt, 'DD/MM/YYYY'),
T5.Response,
T6.Forenames||' '||T6.Surname
from TOU.Users_version_link T1,
TOU.Version T2,
TOU.name T3,
TOU.Admin_Access T4,
Tou.CV_Response T5,
corp.wforce_employee@remote_DWLive T6
where T1.Version_urn=T2.Urn
and T1.Name_urn= T3.urn
and T3.urn = T4.name_urn
and T1.Response_urn=T5.urn
and T1.staff_no=T6.Staff_Number
and Trunc(T1.Response_dt) >= To_date(v_Sdate, 'DD/MM/YYYY')
and Trunc(T1.Response_dt) <= To_date(v_EDate, 'DD/MM/YYYY')
and T4.Staff_No = v_user
and T3.urn = v_nameurn;
End;
And here is the C# code:
this.ConnectToDb();
var cmd = new OracleCommand
{
Connection = cn,
CommandText = "TOU.Stats_By_Date",
CommandType = CommandType.StoredProcedure
};
var id = HttpContext.Current.User.Identity.Name.Split('\\')[1].ToString();
cmd.Parameters.Add("v_SDate", OracleDbType.Varchar2).Value =
startdate.ToString("dd-MM-yyyy");
cmd.Parameters.Add("v_EDate", OracleDbType.Varchar2).Value =
enddate.ToString("dd-MM-yyyy");
cmd.Parameters.Add("v_user", OracleDbType.Decimal).Value = int.Parse(id);
cmd.Parameters.Add("v_nameurn", OracleDbType.Decimal).Value = 3;
var rc = cmd.Parameters.Add("p_cursor", OracleDbType.RefCursor);
rc.Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
this.DisconnectFromDb();
Any suggestions as to what could be wrong please? There are 5 total variables in both pieces of code (4 in, 1 out), which is fine and all of the data types seem to match. I've also tried different variations on the actual v_nameurn
variable, so I've tried 3, "3", and defining it as an Int variable beforehand.
Upvotes: 5
Views: 3028
Reputation: 65594
I've encountered the same error under a different set of circumstances.
With OleDB and earlier versions of Oracle you don't set the return parameter when calling a stored procedure:
PROCEDURE getThingByID
(thingID NUMBER,
results IN OUT tSelectCursor) IS
selectCursor tSelectCursor;
BEGIN
OPEN selectCursor FOR
SELECT Name, Description, IsDeleted
FROM thing WHERE thingID = getThingByID.thingID;
results := selectCursor;
END;
C#/psuedo:
cn = New OleDbConnection("Provider=msdaora.1;Data Source=myTNSEntry;User ID=fakeuser;Password=abc123");
cn.Open();
oleDBCmd = cn.CreateCommand();
oleDBCmd.CommandType = CommandType.StoredProcedure;
oleDBCmd.CommandText = "ThingPackage.GetThingByID";
oleDBCmd.Parameters.Add(new OleDbParameter("thingID", "1"));
We execute it without the tSelectCursor input output parameter:
dataReader = oleDBCmd.ExecuteReader();
As per: C# and Oracle 10g database to call stored procedure
However, it is important to note this works using Oracle 9.2 drivers on a 10g database if you execute this with an Oracle 12c database you get the error:
"ORA-06550: PLS-00306: wrong number or types of arguments in call to 'GETTHINGBYID'"
I've found if you do specify the output parameter it is expecting:
oleDBCmd.Parameters.Add(parm);
You don't get the PLS-00306: wrong number or types of arguments in call to {proc name} error, but when added you get:
size property has an invalid size of 0
This leaves us little choice (I don't know how to overcome this) to resort to the Oracle Managed Data ODP.Net driver.
With ODP.Net you have to set the return parameter when calling the stored procedure, unlike OleDB the Oracle driver provides REFCURSOR output parameters:
PROCEDURE getThingByID2
(thingID NUMBER,
results OUT SYS_REFCURSOR) IS
BEGIN
OPEN refCursor FOR
SELECT Name, Description, IsDeleted
FROM thing WHERE thingID = getThingByID2.thingID;
END;
Now we can easily call this:
ocn = New OracleConnection("Data Source=myTNSEntry;User ID=fakeuser;Password=abc123");
ocn.Open();
ocmd = ocn.CreateCommand();
ocmd.CommandType = CommandType.StoredProcedure();
ocmd.CommandText = "ThingPackage.GetThingByID2";
ocmd.Parameters.Add(New OracleParameter("thingID", "1"));
ocmd.Parameters.Add(New OracleParameter("results", OracleDbType.RefCursor, ParameterDirection.InputOutput));
dataReader = ocmd.ExecuteReader();
For using SSL you may encounter the .Net Oracle SSL Wallet problem 'Network Transport: SSL failure in parsing wallet location': Oracle.ManagedDataAccess to AWS RDS DB - TCPS: Invalid SSL Wallet (Magic)
Upvotes: 0
Reputation: 7415
This is one of those errors where oracle proves to not be a developer friendly RDBMS. Why they can't tell you which of those two problems is the issue I have no idea. I've got a long-winded list of things to check that comes down to the following:
However, from the looks of this, I think i'm going to add one more to my list: Make sure you're calling the procedure you think you are calling. I see the "TOU" qualifier on the procedure. I have to assume this is a schema and not a package based on the sql script. Are you altering the proc in this schema? If you remove the new param in your .net code does it work or do you get the same error? You should get the same error, but if you don't you might be loading the new proc to the wrong schema.
The last thing you can do is just start with a shell of a proc and add one proc at a time until you can figure out what's going on.
I will say that your int.Parse(id) is a bit odd - are your authenticated user IDs just ints? But in any case i'd expect a .net error there and not a oracle error.
Upvotes: 1
Reputation: 77304
cmd.Parameters.Add("v_user", OracleDbType.Decimal).Value = decimal.Parse(id);
cmd.Parameters.Add("v_nameurn", OracleDbType.Decimal).Value = 3m;
You must use a decimal when you are dealing with decimals. For Oracle, decimals don't translate well to ints and the other way round.
Upvotes: 2
Reputation: 13484
Decimal is Oracle NUMBER type
.. So Change your datatype for v_user
and 'v_nameurn'
cmd.Parameters.Add("v_user", OracleDbType.Decimal).Value = int.Parse(id);
cmd.Parameters.Add("v_nameurn", OracleDbType.Decimal).Value = 3;
Upvotes: 2