ASP.NET and Oracle Stored Procedure Error - c#

I am VERY new when it comes to stored procedures and .NET, so I apologize in advance. I have a stored procedure that I am trying to use and I keep getting this error..."wrong number or types of arguments in call to 'COPY_ACCOUNT'". I am not sure why. Below is my stored procedure code followed by my C#.NET code. Any help is GREATLY appreciated. PLEASE.
create or replace procedure abstract_names.copy_account(r_rows_copied out int,
ar_old_acct in abn_headings.acct_no%type,
ar_new_acct in abn_headings.acct_no%type)
is
cnt int := 0;
begin
r_rows_copied := 0;
for r in (select heading from abn_headings where acct_no = ar_old_acct) loop
copy_heading(cnt, ar_old_acct, r.heading, ar_new_acct);
r_rows_copied := r_rows_copied + cnt;
end loop;
dbms_output.put_line('called abstract_names.copy_account '||to_char(r_rows_copied));
return; end;
Then my C#.NET code...
using System.Data.OracleClient;
try
{
conn.Open();
OracleCommand cmd = new OracleCommand();
cmd.Parameters.Add("r_rows_copied", OracleType.Int32).Direction = ParameterDirection.Output;
cmd.Parameters.Add("ar_from_acct", OracleType.VarChar).Value = accountNumberDropDownList.SelectedValue.ToString();
cmd.Parameters.Add("ar_to_acct", OracleType.VarChar).Value = copyAccountDDL.SelectedValue.ToString();
cmd = new OracleCommand("abstract_names.copy_account", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.ExecuteNonQuery();
conn.Close();
/*
abstract_names.copy_account(r_rows_copied out int,
ar_from_acct in abn_headings.acct_no%type,
ar_to_acct in abn_headings.acct_no%type)
*/
}
finally
{
if (conn != null)
conn.Close();
}
My connection string is correct because I use it else where in my code and it works. The commented section is the stored procedure i am trying to use obviously. Please help me!

Just looking at your code and not being familiar with this OracleCommand object, it looks like you're creating parameters and then creating a new object in the middle wiping out all your parameter additions. Create a new object from the connection and then add your parameters. Attempting a stab at better code below. Also I would use using statements for any conneciton,commnand objects to ensure they get closed and disposed.
Edit: Didn't look too deep, my fault. It looks like the parameter names weren't matching up in the stored procedure and the .net code. Also since you're returning a value, I would use the ExecuteScalar method, ExeuteNonQuery won't return any data.
cmd = new OracleCommand("abstract_names.copy_account", conn);
cmd.Parameters.Add("r_rows_copied", OracleType.Int32).Direction = ParameterDirection.Output;
cmd.Parameters.Add("ar_old_acct ", OracleType.VarChar).Value = accountNumberDropDownList.SelectedValue.ToString();
cmd.Parameters.Add("ar_new_acct", OracleType.VarChar).Value = copyAccountDDL.SelectedValue.ToString();
cmd.CommandType = CommandType.StoredProcedure;
object value = cmd.ExecuteScalar();
conn.Close();

You assign a new instance to your cmd variable, then you lose reference to what you had done.
Here:
cmd.Parameters.Add("ar_to_acct", OracleType.VarChar).Value = copyAccountDDL.SelectedValue.ToString();
cmd = new OracleCommand("abstract_names.copy_account", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.ExecuteNonQuery();
conn.Close();
This is the wrong line:
cmd = new OracleCommand("abstract_names.copy_account", conn);
Just by looking at your code, I think you should simply remove that line and it should be OK.

Related

How to call an Oracle Procedure from C#

From C# Code, I'm trying to call a PACKAGE.PROCEDURE() from Oracle. In this simple example I should get one value from the procedure call, but all I get is error:
wrong number or types of arguments in call to 'RETURN_NUM'
The procedure is declared as follows:
PROCEDURE return_num(xNum OUT NUMBER) AS
BEGIN
xNum:= 50;
dbms_output.put_line('hello world ' || xNum);
END;
C# code:
Oraclecon.Open();
OleDbCommand myCMD = new OleDbCommand("TEST.return_num", Oraclecon);
myCMD.CommandType = CommandType.StoredProcedure;
myCMD.Parameters.Add("xNum", OleDbType.Numeric);
OleDbDataReader myReader;
myReader = myCMD.ExecuteReader();
Can some one please point out what I'm doing wrong. Then in a real scenario I would like to call a procedure that returns a set of values from a custom Type, such as:
TYPE r_interface_data IS RECORD
(
object_id VARCHAR2(16),
obj_type VARCHAR2(32)
);
TYPE t_interfase_data IS TABLE OF r_interface_data;
How can I approach that. Thanks!
UPDATE: In my particular case I ended-up doing the following approach
using (OleDbCommand cmd = new OleDbCommand("PACKAGE.procedure_name"))
{
cmd.CommandType = CommandType.StoredProcedure;
SqlManager sqlManager = new SqlManager();
return sqlManager.GetDataSet(cmd);
}
I don't think you're that far off... try this:
OracleCommand cmd = new OracleCommand("return_num", Oraclecon);
cmd.Parameters.Add(new OracleParameter("xNum", OracleDbType.Decimal,
ParameterDirection.Output));
cmd.CommandType = CommandType.StoredProcedure;
cmd.ExecuteNonQuery();
OracleDecimal d = (OracleDecimal)cmd.Parameters[0].Value;
double result = d.ToDouble();
result now contains the out parameter from the procedure.
I think your problem is you were attempting to use a DbDataReader on a stored procedure. DbDataReader is for queries.
Also, I used ODP.net -- that may or may not have contributed to your issue, that you were using Ole.

Procedure or function 'usp_StoredProcName' expects parameter '#inputVal', which was not supplied

I am using a code to call a Stored Procedure having 2 output and 1 input parameter. But i keep getting an error every time I call this stored proc:
CREATE PROCEDURE [dbo].[usp_StoredProcName]
#inputVal nvarchar(255),
#isError bit OUTPUT,
#errorInfo nvarchar(255) OUTPUT
AS BEGIN
DECLARE #totalRow int = 0;
DECLARE #inputValID uniqueidentifier;
SET #isError = 1;
SET #errorInfo = '';
SELECT #inputValID = [inputValID]
FROM testTable
WHERE inputVal = #inputVal;
IF #inputValID IS NULL
BEGIN
SET #isError = 0;
SET #errorInfo = 'inputVal not found';
RETURN
END
END
I have used couple of C# methods to call the stored proc and I get they all return this error:
Procedure or function 'usp_StoredProcName' expects parameter '#inputVal', which was not supplied.
C# Method 1 (to call the stored proc)
using (SqlConnection con = new SqlConnection(myFullConncectionStringToDB))
{
using (SqlCommand cmd = new SqlCommand("usp_StoredProcName", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#inputVal", "MyParamVal_12345");
cmd.Parameters["#isError"].Direction = ParameterDirection.Output;
cmd.Parameters["#errorInfo"].Direction = ParameterDirection.Output;
con.Open();
cmd.ExecuteNonQuery();
var isError = cmd.Parameters["#isError"].Value;
var errInfo = cmd.Parameters["#errorInfo"].Value;
con.Close();
}
}
Method 2 ( to call the stored proc)
SqlConnection con = new SqlConnection(myFullConncectionStringToDB);
SqlCommand cmd = new SqlCommand("usp_StoredProcName", con);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter in_parm = new SqlParameter("#inputVal", SqlDbType.NVarChar);
in_parm.Size = 255;
in_parm.Value = "MyParamVal_12345";
in_parm.Direction = ParameterDirection.Input;
cmd.Parameters.Add(in_parm);
SqlParameter out_parm = new SqlParameter("#errorInfo", SqlDbType.NVarChar);
out_parm.Size = 255;
out_parm.Direction = ParameterDirection.Output;
cmd.Parameters.Add(out_parm);
SqlParameter out_parm1 = new SqlParameter("#isError", SqlDbType.Bit);
out_parm1.Direction = ParameterDirection.Output;
cmd.Parameters.Add(out_parm1);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
Both of the above methods I tried return the same error:
Procedure or function 'usp_StoredProcName' expects parameter '#inputVal', which was not supplied.
Please tell me what am I doing wrong here in my C# code to execute the stored procedure.
I am clearly passing the parameter value in both of my methods but can't figure out why I keep getting this error.
Thank you for your help.
I usually break down the solution into pieces an make sure each one works.
First, test the Stored Procedure to make sure it works as planned. Sample call is below.
-- Switch to your database
USE [YourDatabase]
GO
-- Declare output variables
DECLARE #out_is_error bit;
DECLARE #out_error_info nvarchar(255);
-- Execute sp
EXECUTE [dbo].[usp_StoredProcName]
N'In Data',
#isError = #out_is_error OUTPUT,
#errorInfo = #out_error_info OUTPUT;
-- Show any SQL errors / return data
PRINT ##ERROR;
PRINT 'Error = ' + #out_error_info;
PRINT 'Flag = ';
PRINT CAST(#out_is_error as CHAR(1));
GO
Next, look at the C# piece of the puzzle. Aaron suggestion about correct database is a good one. Do you have two copies of the SP floating around?
Good luck.

PLS-00201: identifier 'schema.cursorname' must be declared

I know there are a couple of other questions on here with the exact same issue, but I am 100% positive I don't have any type of permissions issue. The procedure executes fine from the query editor, but for some reason I can't get this proc to execute from a very simple ASP.net page. I should note this is my first attempt at creating an Oracle Proc.
Here is my code that calls the proc (just trying to call it and force results into the label)
string oradb = "connection string here";
OracleConnection conn = new OracleConnection(oradb);
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = "x.GETCURSORS";
cmd.CommandType = CommandType.StoredProcedure;
OracleParameter ACTNUM = new OracleParameter();
ACTNUM.OracleDbType = OracleDbType.Decimal;
ACTNUM.Direction = ParameterDirection.Input;
ACTNUM.Value ="12345";
cmd.Parameters.Add(ACTNUM);
OracleParameter REJECTS_C = new OracleParameter();
REJECTS_C.OracleDbType = OracleDbType.RefCursor;
REJECTS_C.Direction = ParameterDirection.Output;
cmd.Parameters.Add(REJECTS_C);
try
{
conn.Open();
OracleDataReader objReader = cmd.ExecuteReader();
Label3.Text = objReader.ToString();
}
catch (Exception ex)
{
Label3.Text = string.Format("Exception: {0}", ex.ToString());
}
Package specification:
PACKAGE "x"."REJECTS_DATA" IS
PROCEDURE "GETCURSORS" (
"ACTNUM" IN NUMBER,
"REJECTS_C" OUT SYS_REFCURSOR);
END "REJECTS_DATA";
Package body:
PACKAGE BODY "x"."REJECTS_DATA" IS
PROCEDURE "GETCURSORS" (
"ACTNUM" IN NUMBER,
"REJECTS_C" OUT SYS_REFCURSOR) IS
BEGIN
OPEN REJECTS_C FOR SELECT * FROM x.a
WHERE x.a.ACCOUNT = ACTNUM;
END "GETCURSORS";
END "REJECTS_DATA";
Assuming that the schema name is X, the package name is REJECTS_DATA, and the procedure name is GETCURSORS, at a minimum, the command would need to be
cmd.CommandText = "x.REJECTS_DATA.GETCURSORS";
If you are actually using case-sensitive identifers in PL/SQL (which I would strongly suggest avoiding), you would need to use case-sensitive identifiers in the procedure name as well.
We faced the same issue in our code and had to keep SCHEMA_NAME out of our proc call in C#, i.e. PACKAGE_NAME.PROC_NAME. We resolved this by creating a Synonym in the database with the SCHEMA_NAME

Run stored procedure in C#, pass parameters and capture the output result

This is a simple task that I want to acheive but ASP.NET makes it quite difficult, next to impossible. I followed this question
Running a Stored Procedure in C# Button but found out ExecuteNonQuery does not return the output from query.
I tried this other approach but can't seem to pass the paremeters in this way
SqlConnection myConnection = new SqlConnection(myconnectionString);
SqlCommand myCommand = new SqlCommand();
myCommand.CommandType = CommandType.StoredProcedure;
myCommand.CommandText = "usp_GetCustomer";
myCommand.SelectParameter <-- does not exist
Can someone write this simple code, how can I implement it? Basically I am passing a #username and #month (both character strings) to stored procedure and it returns a number that I want to capture and assign to a label control.
Thank you
The output from my query is this. It runs a complex query, create a temp table and then it runs
select ##rowcount
and I am capturing that.
Don't use SqlCommand.ExecuteNonQuery() if you actually want data from a result set.
Make sure your procedure uses set nocount on
Then use SqlCommand.ExecuteScalar()
return (int)myCommand.ExecuteScalar(); // value of select ##rowcount
Edit: As for your parameters:
myCommand.Parameters.AddWithValue("#username","jsmith");
myCommand.Parameters.AddWithValue("#month","January");
I prefer using linq-to-sql to handle stored procedures. Create a linq-to-sql model, where you add the SP you want to call. This will expose the SP as a function on the generated data context, where the parameters are ordinary C# functions. The returned values will be exposed as a collection of C# objects.
If you have multiple results from the SP things get a bit more complicated, but still quite straight forward.
Use the Parameters collection of the command to set the parameters, and the ExecuteScalar to run the query and get the value from the single-row single-column result.
Use using blocks to make sure that the connection and command are closed and disposed properly in any situation. Note that you have to provide the connection to the command object:
int result;
using (SqlConnection connection = new SqlConnection(myconnectionString)) {
using (SqlCommand command = new SqlCommand(connection)) {
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "usp_GetCustomer";
command.Parameters.Add("#username", SqlDbType.VarChar).Value = username;
command.Parameters.Add("#month", SqlDbType.VarChar).Value = month;
connection.Open();
result = (int)myCommand.ExecuteScalar();
}
}
using(SqlConnection myConnection = new SqlConnection(myconnectionString))
{
SqlCommand myCommand = new SqlCommand();
myCommand.CommandType = CommandType.StoredProcedure;
myCommand.CommandText = "usp_GetCustomer";
myCommand.Parameters.Add("#USER_NAME", SqlDbType.VarChar).Value = sUserName; // user name that you pass to stored procedure
myCommand.Parameters.Add("#Month", SqlDbType.VarChar).Value = iMonth; // Month that you pass to stored procedure
// to get return value from stored procedure
myCommand.Parameters.Add("#ReturnValue", SqlDbType.Int).Direction = ParameterDirection.ReturnValue;
myConnection .Open();
myCommand.ExecuteScalar();
// Returnvalue from stored procedure
return Convert.ToInt32(command.Parameters["#ReturnValue"].Value);
}
Simple code to get return value from SQL Server
SqlConnection myConnection = new SqlConnection(myconnectionString);
SqlCommand myCommand = new SqlCommand();
myCommand.CommandType = CommandType.StoredProcedure;
myCommand.CommandText = "usp_GetCustomer";
myCommand.Parameters.Add("#USER_NAME", SqlDbType.VarChar).Value = sUserName; // user name that you pass to the stored procedure
myCommand.Parameters.Add("#Month", SqlDbType.VarChar).Value = iMonth; //Month that you pass to the stored procedure
// to get return value from the stored procedure
myCommand.Parameters.Add("#ReturnValue", SqlDbType.Int).Direction = ParameterDirection.ReturnValue;
myConnection .Open();
myCommand.ExecuteScalar();
// Returnvalue from the stored procedure
int iReturnValue = Convert.ToInt32(command.Parameters["#ReturnValue"].Value);

C# Oracle execute stored procedure with output parameter

Situation:
I'm trying to run a stored procedure that has an output parameter, which I need to catch.
I use C# 3.5 and the OracleClient with an OleDbConnection.
Research:
I've been looking around for other ways, but as far as I can tell I'm doing it correct. Microsoft support and various other forums.
Problem:
When I do the cmd.ExecuteNonQuery() it just gets stuck. No error or anything, it just stops there and holds the Thread.
When I try via OleDbDataReader or the Scalar it's nothing better.
If I change the CommandText (remove package name) it gives error that it can't find the stored procedure, so I know that is correct at least.
Code:
Oracle:
PROCEDURE deleteThemakaart
(an_seqthemakaart IN NUMBER, an_retval OUT NUMBER)
....
C#:
double InputValue = 777;
try
{
OleDbConnection con = new OleDbConnection(...);
con.Open();
OleDbCommand cmd = new OleDbCommand()
{
CommandText = "thema.pckg_themakaarten.deleteThemakaart",
Connection = con,
CommandType = CommandType.StoredProcedure,
};
OleDbParameter input = cmd.Parameters.Add("an_seqthemakaart", OleDbType.Double);
OleDbParameter output = cmd.Parameters.Add("an_retval", OleDbType.Double);
input.Direction = ParameterDirection.Input;
output.Direction = ParameterDirection.Output;
input.Value = InputValue;
cmd.ExecuteNonQuery();
return (double)output.Value;
}
catch (Exception ex)
{
...
}
finally
{
con.Close();
}
Any help is very welcome :)
Edit: some code is below in comment, but hasn't gotten me any further so far :(
Greetings
I found the trouble maker... one of the tables that the procedure used was locked.

Categories

Resources