C# - Pl/SQL Problem with out parameter in stored procedure - c#

I have a stored procedure which looks like this:
PROCEDURE semifinished_lable_data(p_piece_num_id IN INTEGER,
p_piece_id OUT STRING,
p_tickness OUT NUMBER)
IS begin
select p_piece_id,p_tickness into p_piece_id,p_tickness from piece p where p.piece_num_id=p_piece_num_id;
end;
I've executed it from the database and it worked perfectly. When I execute it from c# app I don't get any value back.
Then when I researched the problem , I added that : cmd.BindByName = true
But this time i got the following error
multiple instances of named argument in list
C# codes :
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.InitialLONGFetchSize = 1000;
var seciliProsedur = "QUA_PRINTING.semifinished_lable_data";
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = seciliProsedur;
cmd.BindByName = true;
object piece_num_id = gridViewMain.GetFocusedRowCellValue(gridViewMain.FocusedColumn);
OracleParameter PAR_ID1 = new OracleParameter();
PAR_ID1.ParameterName = "p_piece_id ";
PAR_ID1.OracleDbType = OracleDbType.Int32;
PAR_ID1.Direction = System.Data.ParameterDirection.Input;
PAR_ID1.Value =piece_num_id;
PAR_ID1.Size = 100;
cmd.Parameters.Add(PAR_ID1);
cmd.Parameters.Add("p_piece_id", OracleDbType.Varchar2, 1000, null, ParameterDirection.Output);
cmd.Parameters.Add("p_tickness", OracleDbType.Double,200, null, ParameterDirection.Output);
conn.Open();
var da = new OracleDataAdapter(cmd);
var dt = new DataTable();
da.Fill(dt);
How can I solve this problem ?

Actually I never used CommandType = CommandType.StoredProcedure.
Try this
cmd.CommandType = CommandType.Text;
seciliProsedur = "BEGIN QUA_PRINTING.semifinished_lable_data(:p_piece_num_id , :p_piece_id, :p_tickness); END;"
OracleParameter PAR_ID1 = new OracleParameter();
PAR_ID1.ParameterName = "p_piece_num_id";
...
cmd.Parameters.Add("p_piece_id", OracleDbType.Varchar2, ParameterDirection.Output);
cmd.Parameters("p_piece_id").DbType = DbType.Varchar2;
cmd.Parameters.Add("p_tickness", OracleDbType.Varchar2, 240, null, ParameterDirection.Output);
cmd.Parameters("p_tickness").DbType = DbType.String;
I think you must set DbType and OracleDbType property.
Then another problem of your code is
var da = new OracleDataAdapter(cmd);
var dt = new DataTable();
da.Fill(dt);
Your procedure does not return any resultSet (i.e. RefCursor), thus above commands do not work. Use
cmd.ExecuteNonQuery()

Related

Executing Oracle stored procedure from C# - wrong number or types of arguments in call

This is the output when I desc the stored procedure:
desc procedure_name
VCOMPTE VARCHAR2 IN
VRESULT REF CURSOR OUT
CLIENT_NO VARCHAR2(6) OUT
ACCT_NAME VARCHAR2(35) OUT
NCG VARCHAR2(6) OUT
NCG_DESC VARCHAR2(35) OUT
AGENCE VARCHAR2(5) OUT
TEL VARCHAR2(50) OUT
This is the C# code I am using to execute it:
public void Validate(string account_num)
{
OracleConnection conn = new OracleConnection(HelperClass.GetConstring());
OracleCommand _cmdObj = conn.CreateCommand();
_cmdObj.CommandText = "pk_xxx.procedure_name";
_cmdObj.CommandTimeout = 1680;
_cmdObj.CommandType = System.Data.CommandType.StoredProcedure;
OracleParameter para_account_num = new OracleParameter();
para_account_num.ParameterName = "VCOMPTE";
para_account_num.OracleDbType = OracleDbType.Varchar2;
para_account_num.Direction = System.Data.ParameterDirection.Input;
para_account_num.Value = account_num;
_cmdObj.Parameters.Add(para_account_num);
OracleParameter VRESULT = new OracleParameter();
VRESULT.ParameterName = "VRESULT";
VRESULT.OracleDbType = OracleDbType.RefCursor;
VRESULT.Direction = System.Data.ParameterDirection.ReturnValue;
_cmdObj.Parameters.Add(VRESULT);
OracleParameter client_no = new OracleParameter();
client_no.ParameterName = "CLIENT_NO";
client_no.OracleDbType = OracleDbType.Varchar2;
client_no.Direction = System.Data.ParameterDirection.ReturnValue;
_cmdObj.Parameters.Add(client_no);
OracleParameter acct_name = new OracleParameter();
acct_name.ParameterName = "ACCT_NAME";
acct_name.OracleDbType = OracleDbType.Varchar2;
acct_name.Direction = System.Data.ParameterDirection.ReturnValue;
_cmdObj.Parameters.Add(acct_name);
OracleParameter ncg = new OracleParameter();
ncg.ParameterName = "NCG";
ncg.OracleDbType = OracleDbType.Varchar2;
ncg.Direction = System.Data.ParameterDirection.ReturnValue;
_cmdObj.Parameters.Add(ncg);
OracleParameter tr_desc = new OracleParameter();
tr_desc.ParameterName = "NCG_DESC";
tr_desc.OracleDbType = OracleDbType.Varchar2;
tr_desc.Direction = System.Data.ParameterDirection.ReturnValue;
_cmdObj.Parameters.Add(tr_desc);
OracleParameter AGENCE = new OracleParameter();
AGENCE.ParameterName = "AGENCE";
AGENCE.OracleDbType = OracleDbType.Varchar2;
AGENCE.Direction = System.Data.ParameterDirection.ReturnValue;
_cmdObj.Parameters.Add(AGENCE);
OracleParameter TEL = new OracleParameter();
TEL.ParameterName = "TEL";
TEL.OracleDbType = OracleDbType.Varchar2;
TEL.Direction = System.Data.ParameterDirection.ReturnValue;
_cmdObj.Parameters.Add(TEL);
try
{
conn.Open();
OracleDataReader reader = _cmdObj.ExecuteReader();
while (reader.Read())
{
//I will use the data
}
}
catch (Exception xc)
{
//catch xc
}
}
But I get an error
Wrong number or types of arguments in call to "procedure_name"."
Debugging is difficult for me because I don't have direct access to the Oracle database, and I am not sure what I am doing wrong. I have successfully executed other stored procedures in the same database. Thanks in advance!
ExecuteReader() is used only for functions, not for procedures. You must use ExecuteNonQuery()
After ExecuteNonQuery() you have to read the result, e.g.
_cmdObj.ExecuteNonQuery();
OracleDataReader reader = ((OracleRefCursor)VRESULT.Value).GetDataReader();
Or create a FUNCTION like
FUNCTION function_name RETURNS SYS_REFCURSOR
VCOMPTE VARCHAR2 IN
CLIENT_NO VARCHAR2(6) OUT
ACCT_NAME VARCHAR2(35) OUT
NCG VARCHAR2(6) OUT
NCG_DESC VARCHAR2(35) OUT
AGENCE VARCHAR2(5) OUT
TEL VARCHAR2(50) OUT
And call it like this
OracleCommand _cmdObj = conn.CreateCommand();
_cmdObj.CommandText = "pk_xxx.procedure_name";
_cmdObj.CommandType = CommandType.StoredProcedure;
_cmdObj.Parameters.Add("res", OracleDbType.RefCursor, ParameterDirection.ReturnValue);
_cmdObj.Parameters.Add("VCOMPTE", OracleDbType.Varchar2, ParameterDirection.Input).Value = account_num;
_cmdObj.Parameters.Add("CLIENT_NO", OracleDbType.Varchar2, ParameterDirection.Output);
_cmdObj.Parameters.Add("ACCT_NAME", OracleDbType.Varchar2, ParameterDirection.Output);
...
OracleDataReader reader = _cmdObj.ExecuteReader();
Maybe have a look at Data Provider for .NET Developer's Guide

Calling stored procedure oracle in c# not all data bound

I need to use an oracle stored procedure in c#. The stored procedure is defined as followsd:
CREATE OR REPLACE PACKAGE MGRWS10.test_mp
as
type tab_assoc_array is table of varchar2(2000) index by binary_integer;
function f_loten(p_item number) return tab_assoc_array;
procedure p_loten(p_item number, o_result out tab_assoc_array);
end;
/
In c# I call the procedure:
using (var cmd = _connection.CreateCommand()){
OracleParameter stringArray = new OracleParameter();
stringArray.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
stringArray.Direction = ParameterDirection.Output;
stringArray.ParameterName = "o_result";
stringArray.Size = 5;
stringArray.ArrayBindSize = new int[5];
cmd.CommandType = CommandType.StoredProcedure;
cmd.BindByName = true;
cmd.CommandText = "test_mp.p_loten(:p_item, :o_result)";
cmd.Parameters.Add("p_item", 12942);
cmd.Parameters.Add(stringArray);
_connection.Open();
await cmd.ExecuteNonQueryAsync();
var x = (string[]) stringArray.Value;
}
When executing the cmd, i get the following error:
RA-01008: not all variables bound
Try this one:
cmd.CommandType = CommandType.Text;
cmd.CommandText = "BEGIN :o_result := test_mp.p_loten(:p_item); END;";
par = cmd.Parameters.Add("o_result", OracleDbType.Varchar2, ParameterDirection.ReturnValue)
par.CollectionType = OracleCollectionType.PLSQLAssociativeArray
cmd.Parameters.Add("p_item", OracleDbType.Int32, ParameterDirection.Input).Value = 12942;
However, I never used PLSQLAssociativeArray as return value, so I don't know whether this code is working.
Maybe return a SYS_REFCURSOR instead of an PLSQLAssociativeArray, this will work for sure.
In this case your C# code may look like this:
cmd.CommandType = CommandType.Text;
cmd.CommandText = "BEGIN :o_result := test_mp.p_loten(:p_item); END;";
cmd.Parameters.Add("o_result", OracleDbType.RefCursor, ParameterDirection.ReturnValue);
cmd.Parameters.Add("p_item", OracleDbType.Int32, ParameterDirection.Input).Value = 12942;
var da = new OracleDataAdapter(cmd); // or cmd.ExecuteNonQueryAsync();
var dt = new DataTable();
da.Fill(dt);

SQL Server CE executes the same prepared statement no matter what

I'm trying to insert some data read from XML files into my database. The problem is that it only executes one prepared statement (the first one i defined) and this causes errors.
This works:
conn = getConnection();
conn.Open();
SqlCeCommand cmd = conn.CreateCommand();
cmd.CommandText = "INSERT INTO ra_gestiuni ([denumire],[id_ra]) Values(#denumire,#id_ra)";
SqlCeParameter numeParam = new SqlCeParameter("#denumire", SqlDbType.NVarChar, 100);
numeParam.Value = denumire;
cmd.Parameters.Add(numeParam);
SqlCeParameter idRAParam = new SqlCeParameter("#id_ra", SqlDbType.Int);
idRAParam.Value = idRA;
cmd.Parameters.Add(idRAParam);
cmd.Prepare();
cmd.ExecuteNonQuery();
cmd.Dispose();
conn.Close();
This does not work anymore:
conn = getConnection();
conn.Open();
SqlCeCommand cmd = conn.CreateCommand();
cmd.CommandText = "INSERT INTO ra_active ([denumire],[gestiune],[utilizator],[tip_activ],[nr_invetar],[categorie_activ],[patrimoniu],[id_ra]) Values(#denumire,#gestiune,#utilizator,#tip_activ,#nr_invetar,#categorie_activ,#patrimoniu,#id_ra)";
SqlCeParameter numeParam = new SqlCeParameter("#denumire", SqlDbType.NVarChar, 100);
numeParam.Value = denumire;
cmd.Parameters.Add(numeParam);
SqlCeParameter gestiuneParam = new SqlCeParameter("#gestiune", SqlDbType.Int);
gestiuneParam.Value = gestiune;
cmd.Parameters.Add(gestiuneParam);
SqlCeParameter utilizatorParam = new SqlCeParameter("#utilizator", SqlDbType.Int);
utilizatorParam.Value = utilizator;
cmd.Parameters.Add(utilizatorParam);
SqlCeParameter nrInventarParam = new SqlCeParameter("#nr_inventar", SqlDbType.NVarChar);
nrInventarParam.Value = nrInventar;
cmd.Parameters.Add(nrInventarParam);
SqlCeParameter categorieActivParam = new SqlCeParameter("#categorie_activ", SqlDbType.NVarChar);
categorieActivParam.Value = categorieActiv;
cmd.Parameters.Add(categorieActivParam);
SqlCeParameter patrimoniuParam = new SqlCeParameter("#patrimoniu", SqlDbType.Int);
patrimoniuParam.Value = patrimoniu;
cmd.Parameters.Add(patrimoniuParam);
SqlCeParameter tipActivParam = new SqlCeParameter("#tip_activ", SqlDbType.Int);
tipActivParam.Value = tipActiv;
cmd.Parameters.Add(tipActivParam);
SqlCeParameter idRAParam = new SqlCeParameter("#id_ra", SqlDbType.Int);
idRAParam.Value = idRA;
cmd.Parameters.Add(idRAParam);
cmd.Prepare();
cmd.ExecuteNonQuery();
cmd.Dispose();
conn.Close();
I get this exception:
The column name is not valid [ Node name (if any) = ,Column name = gestiune ]
This happens because it tries to insert in the previous table (from the previous prepared statement). This is insane, I haven't found any solution to this.
What I see is the parameter #nr_inventar does not exists in your command text (you have #nr_invetar there). Also if you really need to prepare the command before executing, you should set a size for all nvarchar parameters, like you did for #denumire.

Using ouput parameter of type SYS_refcursor

In my database I have a stored procedure with an OUTPUT parameter of type SYS_REFCURSOR. The application side is wrtitten in C#. Can I assign this procedure's output parameter to a Datatable like:
.............
OracleConnection con=new OracleConnection(......);
OracleCommand cmd=new OracleCommand("MyStoredProc",con);
cmd.CommandType=CommandType.StoredProcedure;
cmd.Parameters.Add("REC_CUR",OracleType.Cursor).Direction=ParameterDirection.Output;
con.Open();
cmd.ExecuteNonQuery();
DataTable dt=(DataTable)cmd.Parameters["REC_CUR"].value;//is this legal?
Here's the answer to my own question. If the output parametr of a stored procedure is of type SYS_REFCURSOR then the command
cmd.Parameters["REC_CUR"].value
will return an OracleDataReader object, not a table. And there's no implicit , nor explicit cast from OracledataReader to DataTable.
You can use OracleDataAdapter like below,
sample code with multiple out parameters with RefCursor :
using (OracleCommand cmd = new OracleCommand("SP1", OraCon) { CommandType = System.Data.CommandType.StoredProcedure })
{
var parm_nic = cmd.Parameters.Add("parm_nic", OracleDbType.NVarchar2);
parm_nic.Value = msgBody;
var pram_Name = cmd.Parameters.Add("pram_Name", OracleDbType.NVarchar2, 150, ParameterDirection.Output);
var pram_PAdress = cmd.Parameters.Add("pram_PAdress", OracleDbType.NVarchar2, 150, ParameterDirection.Output);
var output = cmd.Parameters.Add("pram_status", OracleDbType.RefCursor, ParameterDirection.Output);
OraCon.Open();
OracleDataAdapter ad = new OracleDataAdapter(cmd);
OracleCommandBuilder cb = new OracleCommandBuilder(ad);
DataTable dt = new DataTable();
ad.Fill(dt);
var address = pram_PAdress.Value;
var name = pram_Name.Value;
}

How to run the stored procedure that has OUTPUT parameter from C#?

I have a stored procedure with an output parameter. How do I read this value using C# code?
I assume you use ADO.NET? If so, the SqlParameter class has the property "Direction". Set direction to output and after the query has executed you read the value from that parameter.
Something like this:
using (SqlCommand cmd = new SqlCommand("MyStoredProcedure", cn))
{
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter parm = new SqlParameter("#pkid", SqlDbType.Int);
parm.Value = 1;
parm.Direction = ParameterDirection.Input;
cmd.Parameters.Add(parm);
SqlParameter parm2 = new SqlParameter("#ProductName", SqlDbType.VarChar);
parm2.Size = 50;
parm2.Direction = ParameterDirection.Output; // This is important!
cmd.Parameters.Add(parm2);
cn.Open();
cmd.ExecuteNonQuery();
cn.Close();
}

Categories

Resources