Call oracle stored function - c#

I try to call my oracle function, but for some reason i get wiered results from it.
This is my C# code :
using (OracleConnection _conn = new OracleConnection("Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=10.20.190.2)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=DBIDB)));User Id=blng;Password=blng;"))
{
using (OracleCommand cmd = new OracleCommand())
{
_conn.Open();
cmd.Connection = _conn;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "PKG_update_switch.checkexistsinswitch";
cmd.Parameters.Add("phone", OracleDbType.Varchar2, ParameterDirection.Input).Value = phoneToQuery;
cmd.Parameters.Add("res", OracleDbType.Int32, ParameterDirection.ReturnValue);
cmd.ExecuteNonQuery();
result = cmd.Parameters["res"].Value.ToString();
Debug.WriteLine("---" + result);
if (result.Equals("null"))
message = "Didnt find number";
else
message = "Found " + phoneToQuery + " in " + result;
MessageBox.Show(message, "Check Phone Exists",
MessageBoxButtons.OKCancel, MessageBoxIcon.Asterisk);
_conn.Close();
}
}
As a result i always get 0, witch is imposible.
Oracle function:
function checkExistsInSwitch(phone in varchar2) RETURN integer is
tmp varchar2(100):='';
begin
for t in (select c.re_collection_id from re_collection_values c where c.start_range = phone)
loop
----- check that the number is from folder number 2
begin
select o.network_identifier into tmp from operators o where o.switch_folder_id = t.re_collection_id;
return 11;--tmp;
exception
when others then
null;
end;
end loop;
return 11;--'';
end;
this is very wiered, for a stored procedure i get good results, this only happend to my with the stored functions.

Related

Calling stored procedure in C#

I have this stored procedure
create or replace procedure get_login(p_username in varchar2)
is
begin
select USERPASSWORD
from LOGIN
where USERNAME = p_username;
end;
and I try to call it in C# with this
public string login(string username)
{
try
{
conn.Open();
OracleCommand cmd = new OracleCommand("get_login",conn);
cmd.CommandType = CommandType.StoredProcedure;
OracleParameter obja = new OracleParameter("P_USERNAME", OracleDbType.Varchar2, ParameterDirection.Input);
obja.Value = username;
obja.UdtTypeName = "varchar2";
// OracleParameter objb = new OracleParameter("P_USERPASSWORD", OracleDbType.Varchar2, ParameterDirection.Output);
cmd.Parameters.Add(obja);
Login = cmd.ExecuteScalar().ToString();
}
catch(Exception ex)
{
throw ex;
}
finally
{
conn.Close();
}
return Login;
}
but when I run it I get this error:
ORA-06550: Regel 1, kolom 7:
PLS-00306: wrong number or types of arguments in call to 'GET_LOGIN'.
ORA-06550: Regel 1, kolom 7:
PL/SQL: Statement ignored.
System.Exception {Oracle.DataAccess.Client.OracleException}
I'm not really sure what I'm doing wrong here. It might be the procedure but testing that in the database works. I probably did something wrong and I don't know what.
Also if I may ask what does obja.UdtTypeName mean? I followed an example of a friend so I'm not really sure.
P.S: English is not my first language so if I got some terms wrong I'm sorry
edit:
public DBConnect()
{
conn = new OracleConnection();
String pcn = "login";
String pw = "pass";
conn.ConnectionString = "User Id=" + pcn + ";Password=" + pw + ";Data Source=" + "//ipofdatabase" + ";";
}
edit2:
create or replace
procedure get_login(p_username in varchar2)
is
begin
select USERPASSWORD from LOGIN where USERNAME = p_username;
end;
when i do that i get this error:
Error(4,1): PLS-00428: an INTO clause is expected in this SELECT statement
You have only added 1 parameter:
OracleParameter objb = new OracleParameter("P_USERPASSWORD", OracleDbType.Varchar2, ParameterDirection.Output);
cmd.Parameters.Add(obja);
should be:
OracleParameter objb = new OracleParameter("P_USERPASSWORD", OracleDbType.Varchar2, ParameterDirection.Output);
cmd.Parameters.Add(obja);
objb.Size = 255;
cmd.Parameters.Add(objb);
To get the value, change:
Login = cmd.ExecuteScalar().ToString();
To this:
cmd.ExecuteNonQuery();
Login = objb.Value.ToString();

How to call Oracle stored procedure which returns ref cursor

I am trying to call Oracle stored procedure which returns ref cursor, and i need to generate tree view from that returned data. I am new at this and i have two problems.
First problem is that i am not able to call that procedure. I am getting this error: "wrong number or types of arguments in call to 'OBJECT_HIERARCHY'"
And my second problem is that i don't understand how am i gonna get that data when this procedure returns a ref cursor value? There are more then 5000 records in that table and i am not getting that data, but a ref cursor value. Can someone please explain how can i get that data with ref cursor value. I have no experience with Oracle.
This is the procedure definition in oracle:
CREATE OR REPLACE PROCEDURE SAD.object_hierarchy
(nAppId IN NUMBER,
nParentId IN NUMBER DEFAULT -1,
o_cRefCursor OUT SYS_REFCURSOR)
IS
BEGIN
IF NOT o_cRefCursor%ISOPEN THEN
OPEN o_cRefCursor FOR
SELECT
h.PARENT_ID, h.CHILD_ID, h.H_LEVEL,
o.OBJECT_IDENTIFIER, o.OBJECT_TYPE_ID
FROM
(
SELECT
PARENT_ID, CHILD_ID, LEVEL AS H_LEVEL
FROM OBJECT_RELATIONSHIPS
START WITH PARENT_ID = nParentId --> -1 --= 60170
CONNECT BY PRIOR CHILD_ID = PARENT_ID
) h
INNER JOIN
OBJECTS o
ON
o.OBJECT_ID = h.CHILD_ID AND
O.APPLICATION_ID = nAppId;
END IF;
END object_hierarchy;
these are the table field definitions
Column Name Data Type
OBJECT_REL_ID NUMBER (14)
PARENT_ID NUMBER (14)
CHILD_ID NUMBER (14)
OBJECT_IDENTIFIER VARCHAR2 (255 Byte)
OBJECT_TYPE_ID VARCHAR2 (5 Byte)
and this is my code which returns error:
string oradb = "Data Source=(DESCRIPTION="
+ "(ADDRESS=(PROTOCOL=TCP)(HOST=tnt33)(PORT=1521))"
+ "(CONNECT_DATA=(SERVICE_NAME=ORCL)));"
+ "User Id=xxx;Password=xxxxx;";
OracleConnection con = new OracleConnection(oradb);
try
{
con.Open();
OracleCommand cmd = new OracleCommand();
cmd.Connection = con;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "SAD.object_hierarchy";
cmd.Parameters.Add("nAppId", OracleDbType.Int16).Value = 1;
OracleParameter oraP = new OracleParameter();
oraP.OracleDbType = OracleDbType.RefCursor;
oraP.Direction = System.Data.ParameterDirection.Output;
cmd.Parameters.Add(oraP);
OracleDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
}
reader.Close();
}
catch (Exception ex)
{
con.Close();
}
Can someone please help me and explain to me why is my code returning this error: "wrong number or types of arguments in call to 'OBJECT_HIERARCHY'"
Example:
string connStr = "Data Source=...";
DataSet dataset = new DataSet();
string connStr = ConfigurationManager.ConnectionStrings["OracleConn"].ToString();
using (OracleConnection objConn = new OracleConnection(connStr))
{
OracleCommand cmd = new OracleCommand();
cmd.Connection = objConn;
cmd.CommandText = "Oracle_PkrName.Stored_Proc_Name";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("Emp_id", OracleType.Int32).Value = 3; // Input id
cmd.Parameters.Add("Emp_out", OracleType.Cursor).Direction = ParameterDirection.Output;
try
{
objConn.Open();
cmd.ExecuteNonQuery();
OracleDataAdapter da = new OracleDataAdapter(cmd);
da.Fill(dataset);
}
catch (Exception ex)
{
System.Console.WriteLine("Exception: {0}", ex.ToString());
}
objConn.Close();
}
If you're going to provide the OUT, you'll need to provide nParentId as well because .NET isn't going to name those parameters when the statement is sent to the server.
cmd.Parameters.Add("nParentId", OracleDbType.Int16).Value = -1;

Invalid length parameter passed to LEFT or SUBSTRING function

I got this error mess "Invalid length parameter passed to LEFT or SUBSTRING function" from this below. Anyone can give me a hint what cause this, and how I can solve it?
string cmdText = #"Declare #SqlString nvarchar(2500)
, #AreaDelimiter char(1)
, #AreaFilter nvarchar(max);
Select #AreaDelimiter = ','
If (#AreaName Not Like '*')
Begin
Set #AreaName = #AreaName + #AreaDelimiter
Set #AreaFilter = ''
While LEN(#AreaName) > 0
Begin
If (Len(#AreaFilter) > 0)
Begin
Set #AreaFilter = #AreaFilter + ' Or Area Like ''' +
LTRIM(SubString(#AreaName, 1,
CharIndex(#AreaDelimiter, #AreaName) - 1)) + '%'''
End
Else
Begin
Set #AreaFilter = 'Area Like ''' +
LTRIM(SubString(#AreaName, 1,
CharIndex(#AreaDelimiter, #AreaName) - 1)) + '%'''
End
Select #AreaName = SUBSTRING(#AreaName, CharIndex(#AreaDelimiter,
#AreaName) + 1, Len(#AreaName))
End
End"
this code above continues with the else statement and the others operations who works :)
And this is my C# code:
string area = "AREA1,AREA2,AREA3";
using (SqlConnection conn = new SqlConnection(domain.getDecryptedSqlConnectionString(domain.name + passPhrase)))
{
using (SqlCommand cmd = new SqlCommand(cmdText, conn))
{
System.Globalization.CultureInfo cInfo = new System.Globalization.CultureInfo("pt-BR");
DateTime dt = DateTime.Parse(startDate, cInfo);
DateTime da = DateTime.Parse(endDate, cInfo);
cmd.Parameters.Add("Interval", SqlDbType.Int).Value = interval;
cmd.Parameters.Add("IntervalUnit", SqlDbType.VarChar).Value = intervalUnit;
cmd.Parameters.Add("StartDate", SqlDbType.DateTime).Value = dt.ToShortDateString();
cmd.Parameters.Add("EndDate", SqlDbType.DateTime).Value = da.ToShortDateString();
cmd.Parameters.Add("tbName", SqlDbType.VarChar).Value = domain.alarmTableName;
cmd.Parameters.Add("AreaName", SqlDbType.VarChar).Value = area;
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
using (DataTable tb = new DataTable())
{
try
{
conn.Open();
adapter.Fill(tb);
return tb;
}
catch (Exception ex)
{
return tb;
}
finally
{
conn.Close();
}
}
}
}
}
SOLVED, I JUST CHANGE
cmd.Parameters.Add("AreaName", SqlDbType.VarChar).Value = area;
FOR
cmd.Parameters.Add("AreaName", SqlDbType.VarChar, -1).Value = area;
I can reproduce the error with
DECLARE #AreaName VARCHAR(20);
DECLARE #AreaDelimiter CHAR(1);
DECLARE #AreaFilter VARCHAR(100);
SET #AreaName='AREA1,AREA2,AREA3,area4,area5';
SET #AreaDelimiter=',';
Notice that the declaration of #AreaName is not long enough for the data - check your declaration.
Also, if the string for #AreaName has come from user input, your code is vulnerable to SQL injection attacks.
EDIT:
All your SQL parameter names need to start with #, e.g. #AreaName, and you must match up the SqlDbType between your C# code and the SQL code.
You shouldn't be using
cmd.Parameters.Add("StartDate", SqlDbType.DateTime).Value = dt.ToShortDateString();
instead it should be
cmd.Parameters.Add("StartDate", SqlDbType.DateTime).Value = dt;
because dt is already a DateTime.

Stored Procedures with Mysql connector

I'm trying to call a simple stored procedure in c# 2010.
With only a IN argument it's ok, but now with a OUT argument it's not working.
In phpmyadmin :
drop procedure if exists insert_artist;
delimiter $$
create procedure insert_student(IN name VARCHAR(100), OUT id INT)
begin
insert into student(name) values(name);
set id = last_insert_id();
end$$
delimiter ;
Then using
call insert_student("toto",#id);
select #id;
It's working fine.
Now, in c# :
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
connection.Open();
using (MySqlCommand command = connection.CreateCommand())
{
command.CommandText = "insert_student";
command.CommandType = System.Data.CommandType.StoredProcedure;
command.Parameters.AddWithValue("#name", "xxxx");
command.Parameters.AddWithValue("#id",MySqlDbType.Int32);
command.ExecuteNonQuery();
Console.WriteLine("**** " + command.Parameters["#id"].Value);
}
}
Gives me an exception when executing ExecuteNonQuery() :
OUT or INOUT argument 2 for routine insert_student is not a variable or NEW pseudo-variable in BEFORE trigger
The same thing without the out argument in the stored procedure is working fine.
Where is my mistake?
A fuller example:
if (this.OpenConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(nameOfStoredRoutine, connection);
cmd.CommandType = CommandType.StoredProcedure;
//input parameters
for (int i = 0; i < (parameterValue.Length / 2); i++)
{
cmd.Parameters.AddWithValue(parameterValue[i, 0], parameterValue[i, 1]);
cmd.Parameters[parameterValue[i, 0]].Direction = ParameterDirection.Input;
parameterList = parameterList + parameterValue[i,0] + " " + parameterValue[i,1] + " ";
}
//single output parameter
cmd.Parameters.AddWithValue("#output", MySqlDbType.Int32);
cmd.Parameters["#output"].Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery(); //Execute command
this.CloseConnection(); //close connection
return Convert.ToInt32(cmd.Parameters["#output"].Value.ToString());
my below code works
pls check if it's ok for you.
InsertQuery = New MySqlCommand("xxxxxx")
InsertQuery.Connection = Connection
InsertQuery.CommandType = Data.CommandType.StoredProcedure
InsertQuery.Parameters.AddWithValue("IN_xxx", str_xxxx)
InsertQuery.Parameters.Add("OUT_LastID", MySqlDbType.Int32).Direction = ParameterDirection.Output
IQ = InsertQuery.ExecuteReader()
IQ.Read()
LASTID = InsertQuery.Parameters("OUT_LastID").Value

Get return values from a stored procedure in c# (login process)

I am trying to use a Stored Procedure which takes two parameters (login, pw) and returns the user info.
If I execute the SP manually, I get
Session_UID User_Group_Name Sys_User_Name
------------------------------------ -------------------------------------------------- -
NULL Administrators NTMSAdmin
No rows affected.
(1 row(s) returned)
#RETURN_VALUE = 0
Finished running [dbo].[p_SYS_Login].
But with the code below, I only get the return value.
do you know how to get the other values shown above like
Session_UID, User_Group_Name, and Sys_User_Name ?
if you see the commented part below code. I tried to add some output parameters but it doesn't work with incorrect number of parameters error.
string strConnection = Settings.Default.ConnectionString;
using (SqlConnection conn = new SqlConnection(strConnection))
{
using (SqlCommand cmd = new SqlCommand())
{
SqlDataReader rdr = null;
cmd.Connection = conn;
cmd.CommandText = "p_SYS_Login";
//cmd.CommandText = "p_sys_Select_User_Group";
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter paramReturnValue = new SqlParameter();
paramReturnValue.ParameterName = "#RETURN_VALUE";
paramReturnValue.SqlDbType = SqlDbType.Int;
paramReturnValue.SourceColumn = null;
paramReturnValue.Direction = ParameterDirection.ReturnValue;
//SqlParameter paramGroupName = new SqlParameter("#User_Group_Name", SqlDbType.VarChar, 50);
//paramGroupName.Direction = ParameterDirection.Output;
//SqlParameter paramUserName = new SqlParameter("#Sys_User_Name", SqlDbType.VarChar, 50);
//paramUserName.Direction = ParameterDirection.Output;
cmd.Parameters.Add(paramReturnValue);
//cmd.Parameters.Add(paramGroupName);
//cmd.Parameters.Add(paramUserName);
cmd.Parameters.AddWithValue("#Sys_Login", textUserID.Text);
cmd.Parameters.AddWithValue("#Sys_Password", textPassword.Text);
try
{
conn.Open();
object result = cmd.ExecuteNonQuery();
int returnValue = (int)cmd.Parameters["#RETURN_VALUE"].Value;
if (returnValue == 0)
{
Hide();
Program.MapForm.Show();
}
else if (returnValue == 1)
{
MessageBox.Show("The username or password you entered is incorrect", "NTMS Login", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else if (returnValue == 2)
{
MessageBox.Show("This account is disabled", "NTMS Login", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
MessageBox.Show("Database error. Please contact administrator", "NTMS Login", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
catch (Exception ex)
{
string message = ex.Message;
string caption = "MAVIS Exception";
MessageBoxButtons buttons = MessageBoxButtons.OK;
MessageBox.Show(
message,
caption,
buttons,
MessageBoxIcon.Warning,
MessageBoxDefaultButton.Button1);
}
}
}
Thanks for your help.
Have you tried with Try with ParameterDirection.Output?
SqlParameter paramReturnValue = new SqlParameter();
paramReturnValue.ParameterName = "#RETURN_VALUE";
paramReturnValue.Direction = ParameterDirection.Output;
...
conn.Open();
cmd.Connection = conn;
cmd.ExecuteNonQuery();
...
int returnValue = (int)cmd.Parameters["#RETURN_VALUE"].Value;
If your SP uses an OUT parameter, like this:
CREATE PROC FOO(#bar INT OUT) AS
SELECT #bar = 1
Then you need to use the ParameterDirection.Output when setting up your SqlCommand object.
However, if your SP uses the RETURN keyword, like this:
CREATE PROC FOO(#bar INT OUT) AS
RETURN 1 -- NOTE the RETURN
Then you have to use ParameterDirection.ReturnValue. I suspect the former case is the good one.
See this previous question
You need to call ExecuteReader method on the cmd object and read the output by using Read method of the SqlDataReader class.
Here is an example: SqlDataReader.Read method.

Categories