I have error 'Error converting data type nvarchar to decimal'
when call stored procedure call another stored procedure from C# as
cmd = new SqlCommand("tax_Base_emp", con);
cmd.CommandType = CommandType.StoredProcedure;
parm1 = new SqlParameter("#emp_code", SqlDbType.BigInt);
parm1.Value = emp_code;
parm1.Direction = ParameterDirection.Input;
cmd.Parameters.Add(parm1);
parm2 = new SqlParameter("#co_id", SqlDbType.BigInt);
parm2.Value = Settings.Default.comp_id;
parm2.Direction = ParameterDirection.Input;
cmd.Parameters.Add(parm2);
parm3 = new SqlParameter("#d", SqlDbType.DateTime);
parm3.Value = Convert.ToDateTime("31/1/2010");
parm3.Direction = ParameterDirection.Input;
cmd.Parameters.Add(parm3);
parm4 = new SqlParameter("#y", SqlDbType.Int);
parm4.Value =int.Parse(textBox2.Text);
parm4.Direction = ParameterDirection.Input;
cmd.Parameters.Add(parm4);
parm5 = new SqlParameter("#check_month", SqlDbType.Int);
parm5.Value =1;
parm5.Direction = ParameterDirection.Input;
cmd.Parameters.Add(parm5);
parm6 = new SqlParameter("#month", SqlDbType.Int);
parm6.Value =8;
parm6.Direction = ParameterDirection.Input;
cmd.Parameters.Add(parm6);
SqlParameter parm7 = new SqlParameter("#indate", SqlDbType.DateTime);
parm7.Value = Convert.ToDateTime("8/5/2010");
parm7.Direction = ParameterDirection.Input;
cmd.Parameters.Add(parm7);
SqlParameter parm8 = new SqlParameter("#Sumtotal", SqlDbType.Decimal);
parm8.Scale = 2;
parm8.Direction = ParameterDirection.Output;
cmd.Parameters.Add(parm8);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
decimal tax_value = Convert.ToDecimal(cmd.Parameters["#Sumtotal"].Value);
And the stored proecdure called:
ALTER PROCEDURE Tax_Base_emp
#emp_code bigint,
#co_id bigint,
#d datetime,
#y int,
#check_month int,
#month int,
#indate datetime,
#Sumtotal decimal(8,2) output
AS
declare #tax_main_sal decimal(8,2)
declare #tax_var_sal decimal(8,2)
declare #salary decimal(8,2)
declare #insh_varsalary decimal(8,2)
declare #insh_value decimal(8,2)
declare #vacation_value decimal(8,2)
declare #vacation_varsalary decimal(8,2)
declare #ded_value decimal(8,2)
declare #ben_value decimal(8,2)
exec Taxable_mainsalary #emp_code,#co_id,#tax_main_sal output
exec taxable_varsalary #emp_code,#co_id, #tax_var_sal output
----taxableSalary---------------
set #salary=#tax_main_sal+#tax_var_sal
----insurance-------------------
exec varsalary_insh #emp_code,#co_id,#d,#y, #insh_varsalary output
exec insh_no #emp_code,#co_id,#insh_varsalary,#check_month, #insh_value output
----vacation--------------------
exec vacation_varsalary #emp_code,#co_id,#vacation_varsalary output
exec vacation_value #emp_code,#co_id,#y,#month,#vacation_varsalary,output
---------deduction---------------
exec deduction_for_tax #emp_code,#co_id,#indate,#ded_value output
-------------benifit------------
exec benfit_for_tax #emp_code,#co_id,#indate,#ben_value output
-----------------------------------NetSalary--------------------------------------------------------
set #Sumtotal=(isnull(#salary,0)+isnull(#ben_value,0))-(isnull(#insh_value,0)+isnull(#vacation_value,0)+isnull(#ded_value,0))
return
I don't see anything wrong with your C# code - it's really hard to tell what would be causing the problem. Your C# code is just simply calling a single stored proc - that shouldn't be a problem, really.
However, I do have a few recommendations for your coding style:
put your SqlConnection and SqlCommand into using(....) { .... } blocks to make your code more reliable
try to avoid specifying default property values, like Direction = ParameterDirection.Input; over and over again; the .Input is the default - only specify it when you deviate from that default
if you do the same steps over and over and over again - why don't you put this in a method and call that method a couple of times?? This also saves you from having to create a gazillion of SqlParameter objects that you then just throw away .....
You'd end up with something like:
public void CallStoredProc()
{
using(SqlConnection con = new SqlConnection(.....))
using(SqlCommand cmd = new SqlCommand("tax_Base_emp", con))
{
cmd.CommandType = CommandType.StoredProcedure;
AddParameter(cmd.Parameters, "#emp_code", SqlDbType.BigInt, emp_code);
AddParameter(cmd.Parameters, "#co_id", SqlDbType.BigInt, comp_id);
AddParameter(cmd.Parameters, "#d", SqlDbType.DateTime, Convert.ToDateTime("31/1/2010"));
AddParameter(cmd.Parameters, "#y", SqlDbType.Int, int.Parse(textBox2.Text));
AddParameter(cmd.Parameters, "#check_month", SqlDbType.Int, 1);
AddParameter(cmd.Parameters, "#month", SqlDbType.Int, 8);
AddParameter(cmd.Parameters, "#indate", SqlDbType.DateTime, Convert.ToDateTime("8/5/2010"));
AddOutputParameter(cmd.Parameters, "#Sumtotal", SqlDbType.Decimal, 8, 2);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
decimal tax_value = Convert.ToDecimal(cmd.Parameters["#Sumtotal"].Value);
}
}
public void AddParameter(SqlParameterCollection params, string name, SqlDbType type, object value)
{
SqlParameter tmpParam = new SqlParameter(name, type);
tmpParam.Value = value;
params.Add(tmpParam);
}
public void AddOutputParameter(SqlParameterCollection params, string name, SqlDbType type, int precision, int scale)
{
SqlParameter tmpParam = new SqlParameter(name, type);
tmpParam.ParameterDirection = Direction.Output;
tmpParam.Precision = precision;
tmpParam.Scale = scale;
params.Add(tmpParam);
}
I can't see anything in the code you have posted that would cause that.
I suspect that the error is in one of the 8 stored procedures you are calling where you are assigning an nvarchar to a decimal.
I'd comment these all out temporarily and just return a dummy number if that fixes it uncomment half and try again. If the error reoccurs then you know it is in one of the ones you just uncommented. i.e. do a binary search to find the offending procedure.
Related
From my C# program, I need to call a stored procedure in an Oracle database, which has the following contract:
PKG_ENTITY.ALTER_ENTITY (VARCHAR2 NAME, VARCHAR2 FULLNAME, ATTRS_TYPE ATTRS, VARCHAR2 STATUS, INTEGER OUT RESULT, VARCHAR2 OUT ERRORMSG).
The RESULT and ERRORMSG parameters are OUT parameters.
I know about the ATTRS_TYPE type that it is specified:
TYPE ATTRS_TYPE IS TABLE OF VARCHAR2(2000) INDEX BY VARCHAR2(30);
I used to call this stored procedure as follows:
private void ExecuteNonQuery(string query, params OracleParameter[] parameters)
{
using (var connection = new OracleConnection(_connectionString))
{
var command = new OracleCommand(query, connection) { CommandType = CommandType.Text };
connection.Open();
command.Parameters.AddRange(parameters);
command.ExecuteNonQuery();
}
}
where query =
DECLARE
tNAME varchar2(100);
tATTRS PKG_ENTITY.ATTRS_TYPE;
tRESULT INTEGER;
tERRORMSG varchar2(100);
BEGIN
tNAME := :pEntityId;
tATTRS(:pPropId) := :pPropValue;
PKG_ENTITY.ALTER_ENTITY(tUSERNAME,NULL,tATTRS,NULL,tRESULT,tERRORMSG);
END;
Parameter values: pEntityId, pPropId and pPropValue are defined in the code.
Everything was fine, but then I received the requirement that it is necessary to log out values of the tRESULT and tERRORMSG parameters and with this I had great difficulties. I wanted to modify the query by adding a SELECT after calling the stored procedure. Like that:
DECLARE
tNAME varchar2(100);
tATTRS PKG_ENTITY.ATTRS_TYPE;
tRESULT INTEGER;
tERRORMSG varchar2(100);
BEGIN
tNAME := :pEntityId;
tATTRS(:pPropId) := :pPropValue;
PKG_USER.ALTER_USER(tUSERNAME,NULL,tATTRS,NULL,tRESULT,tERRORMSG);
SELECT tRESULT, tERRORMSG FROM DUAL;
END;
But such a query is not correct from the point of view of the pl/sql language. Therefore, I came to the conclusion that I need to use the stored procedure call directly and the code should look something like this:
private ProcedureResult ExecuteStoredProcedure(string procedureName)
{
using (var connection = new OracleConnection(_connectionString))
{
var command = new OracleCommand(procedureName, connection) { CommandType = CommandType.StoredProcedure };
connection.Open();
command.Parameters.Add("NAME", OracleDbType.Varchar2, "New name", ParameterDirection.Input);
command.Parameters.Add("FULLNAME", OracleDbType.Varchar2, "New fullname", ParameterDirection.Input);
var attr = new EntityAttribute() { attribute1 = "id", attribute2 = "value"};
command.Parameters.Add("ATTRS", EntityAttribute, "New fullname", ParameterDirection.Input);
command.Parameters.Add("STATUS", OracleDbType.Varchar2, "Status", ParameterDirection.Input);
command.Parameters.Add("RESULT", OracleDbType.Int32).Direction = ParameterDirection.Output;
command.Parameters.Add("ERRORMSG", OracleDbType.Varchar2).Direction = ParameterDirection.Output;
command.ExecuteNonQuery();
return new ProcedureResult()
{
StatusCode = int.Parse(command.Parameters["RESULT"].Value.ToString()),
Message = command.Parameters["ERRORMSG"].Value.ToString()
};
}
}
And here I had difficulties with the PKG_ENTITY.ATTRS_TYPE type definition.
TYPE ATTRS_TYPE IS TABLE OF VARCHAR2 (2000) INDEX BY VARCHAR2 (30);
I know that there is an IOracleCustomType interface, but I don’t understand how to implement it correctly.
For example
[OracleCustomTypeMapping("PKG_ENTITY.ATTRS_TYPE")]
public class EntityAttribute : INullable, IOracleCustomType
{
[OracleObjectMapping("ATTRIBUTE1")]
public string attribute1 { get; set; }
[OracleObjectMapping("ATTRIBUTE2")]
public string attribute2 { get; set; }
public bool IsNull => throw new System.NotImplementedException();
public void FromCustomObject(OracleConnection con, IntPtr pUdt)
{
throw new NotImplementedException();
}
public void ToCustomObject(OracleConnection con, IntPtr pUdt)
{
throw new NotImplementedException();
}
}
What should be the names of the fields of this class? I understand that 'ATTRIBUTE1' and 'ATTRIBUTE2' are not valid names.
This answer states that you cannot pass an INDEX BY VARCHAR2 associative array in C#. Instead, you can build the associative array in an anonymous PL/SQL block and call the procedure from there (as you were doing originally).
So you could use:
DECLARE
tATTRS PKG_ENTITY.ATTRS_TYPE;
BEGIN
tATTRS(:pPropId) := :pPropValue;
PKG_USER.ALTER_USER(
NAME => :pEntityId,
USERNAME => NULL,
ATTRS => tATTRS,
STATUS => NULL,
RESULT => :pResult,
ERRORMSG => :pErrorMsg
);
END;
Then pass in the parameters pPropId, pPropValue and pEntityId with the direction of ParameterDirection.Input as you were doing and pass pResult and pErrorMsg with the direction of ParameterDirection.Output.
The signature of the PL stored procedure should be
PKG_ENTITY.ALTER_ENTITY (VARCHAR2 NAME, VARCHAR2 FULLNAME, ATTRS_TYPE ATTRS, VARCHAR2 STATUS, INTEGER OUT RESULT, VARCHAR2 OUT ERRORMSG)
Do note that OUT was added to the parameter declaration.
And in the c#code you would need to make sure the parameters are marked as output
.Parameters.Add("RESULT", OracleDbType.Int32).Direction = ParameterDirection.Output;
Once done, you would just need to assign the desired value to the parameters in your PL/SQL stored procedure.
RESULT:= 0;
Calling a PL/SQL procedure is much simpler (not tested, but I assume you will get the idea):
var cmd = new OracleCommand("BEGIN PKG_ENTITY.ALTER_ENTITY(:NAME, :FULLNAME, :ATTRS, :STATUS, :RESULT, :ERRORMSG); END;"), connection);
cmd.CommandType = CommandType.Text;
// should work as well
// var cmd = new SqlCommand("PKG_ENTITY.ALTER_ENTITY(:NAME, :FULLNAME, :ATTRS, :STATUS, :RESULT, :ERRORMSG)"), connection);
// cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("NAME", OracleDbType.Varchar2, ParameterDirection.Input).Value = "New name"
cmd.Parameters.Add("FULLNAME", OracleDbType.Varchar2, ParameterDirection.Input).Value = "New fullname"
par = cmd.Parameters.Add("ATTRS", OracleDbType.Varchar2, ParameterDirection.Input);
par.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
var arr string[] = new string[] {"id" , "value"};
par.Value = arr;
par.Size = arr .Count;
cmd.Parameters.Add("STATUS", OracleDbType.Varchar2, ParameterDirection.Input).Value = "Status";
cmd.Parameters.Add("RESULT", OracleDbType.Int32, ParameterDirection.Output);
cmd.Parameters("RESULT").DbType = DbType.Int32;
cmd.Parameters.Add("ERRORMSG", OracleDbType.Varchar2, 100, null, ParameterDirection.Output);
cmd.Parameters("ERRORMSG").DbType = DbType.String;
cmd.ExecuteNonQuery();
var result = System.Convert.ToInt32(cmd.Parameters("RESULT").Value);
var errmsg = cmd.Parameters("ERRORMSG").Value.ToString();
Maybe this one helps: PL/SQL Associative Array Binding
Actually, I don't remember anymore why I do cmd.Parameters("RESULT").DbType = DbType.Int32;. Perhaps it was needed to make my code compatible for ODP.NET Provider 1.x and 2.0, see Mandatory Migration of .NET 1.x Stored Procedures to .NET 2.0 or Later
I have defined output parameter as shown below:
C#:
scom.Parameters.Add("#User_ID",SqlDbType.VarChar,8).Direction = ParameterDirection.Output ;
Sql:
#User_ID varchar(8) output
I am getting complete string when executing procedure in Sql Server, but getting only first character in C#. I searched a lot and ensured that size is defined in both C# and Sql. Even I tried with fixed length character (Char(8)), but still getting only first character in C#. Please let me know what is the issue.
C# Code:
public bool CheckPhone(string phoneNumber)
{
SqlConnection myconn=new SqlConnection(connectionString);
try
{
myconn.Open();
SqlCommand scom = new SqlCommand("AuthenticatePhone", myconn);
scom.CommandType = CommandType.StoredProcedure;
scom.Parameters.Add("#phoneNumber", SqlDbType.BigInt).Value = Convert.ToInt64(phoneNumber);
scom.Parameters.Add("#User_ID", SqlDbType.Char, 8).Direction = ParameterDirection.Output;
scom.Parameters.Add("#User_Name", SqlDbType.Char, 120).Direction = ParameterDirection.Output;
scom.ExecuteNonQuery();
if (scom.Parameters["#User_Name"] == null)
{
return false;
}
else
{
UserID = (string)scom.Parameters["#User_ID"].Value;//.ToString();
UserName = (string)scom.Parameters["#User_Name"].Value;//.ToString();
myconn.Close();
return true;
}
}
catch (Exception e)
{
string error = e.InnerException + e.Message;
}
finally
{
myconn.Close();
}
return false;
}
Sql:
Create procedure dbo.AuthenticatePhone
#phoneNumber numeric(11,0) ,
#User_ID varchar(8) output ,
#User_Name varchar(120) output
as
begin
Select #User_ID = convert(varchar(8),[User_ID]) ,
#User_Name = [User_Name]
from dbo.NRE_Users
where PhoneNumber = #phoneNumber
;
print #User_ID
print #User_Name
end
Try to use the below code:
Parameter[param number].Size = 200;
Doesn't repro for me. Given this stored procedure:
create procedure dbo.AuthenticatePhone
#phoneNumber numeric(11,0) ,
#User_ID varchar(8) output ,
#User_Name varchar(120) output
as
set #User_ID = '1234567890' -- should be truncated to '12345678'
set #User_Name = 'The quick brown fox jumped over the lazy dog.'
return 0
go
Running this SQL in SSMS:
declare #userId varchar(1000) = 'xxx'
declare #userName varchar(1000) = 'yyy'
exec AuthenticatePhone 1 , #User_ID = #userId out , #User_Name = #userName out
select #userId,#userName
results in the expected results:
#userId contains the expected 12345678
#userName contains the expected The quick brown fox jumped over the lazy dog.
Executing it via C#:
using ( SqlConnection connection = new SqlConnection( "Server=localhost;Database=sandbox;Trusted_Connection=True;" ) )
using ( SqlCommand command = connection.CreateCommand() )
{
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "dbo.AuthenticatePhone" ;
SqlParameter phoneNumber = new SqlParameter {
ParameterName = "#phoneNumber" ,
IsNullable = true ,
Direction = ParameterDirection.Input ,
Value = 2125551212L ,
} ;
command.Parameters.Add( phoneNumber ) ;
SqlParameter userId = new SqlParameter {
ParameterName = "#User_ID" ,
IsNullable = true ,
Direction = ParameterDirection.Output ,
DbType = DbType.String ,
Size = 1000 ,
Value = DBNull.Value ,
} ;
command.Parameters.Add( userId ) ;
SqlParameter userName = new SqlParameter {
ParameterName = "#User_Name" ,
IsNullable = true ,
Direction = ParameterDirection.Output ,
DbType = DbType.String ,
Size = 1000 ,
Value = DBNull.Value ,
} ;
command.Parameters.Add( userName ) ;
connection.Open() ;
int rowsAffected = command.ExecuteNonQuery() ;
connection.Close() ;
Console.WriteLine( "Rows Affected: {0}" , rowsAffected ) ;
Console.WriteLine( "User ID: {{{0}}}" , userId.Value as string ) ;
Console.WriteLine( "User Name: {{{0}}}" , userName.Value as string ) ;
}
likewise results in the expected
Rows Affected: -1
User ID: {12345678}
User Name: {The quick brown fox jumped over the lazy dog.}
Even substituting your parameter definitions:
command.Parameters.Add("#phoneNumber", SqlDbType.BigInt).Value = 2125551212L ;
command.Parameters.Add("#User_ID", SqlDbType.Char, 8).Direction = ParameterDirection.Output;
command.Parameters.Add("#User_Name", SqlDbType.Char, 120).Direction = ParameterDirection.Output;
You get the expected results.
Though you might note that SqlDbType.Char is a SQL char(X). It's equivalent of `convert(char(120),'John Doe') in T-SQL. The .Net string will wind up padded with spaces to the specified length.
You might consider changing the type specifier to SqlDbType.VarChar: it will match the parameter declaration in the stored procedure and you won't find yourself needing to trim trailing whitespace from the string to make it useful.
change SqlDbType.Char to SqlDbType.VarChar
here:
scom.Parameters.Add("#User_ID", SqlDbType.Char, 8).Direction = ParameterDirection.Output;
scom.Parameters.Add("#User_Name", SqlDbType.Char, 120).Direction = ParameterDirection.Output;
As far as I know a char in .net is only one character long. So you will need to change the parameter type to varchar
scom.Parameters.Add("#User_ID", SqlDbType.Varchar, 8).Direction = ParameterDirect
I have a stored procedure called SelFromWeather2 and I need to return values from table. When I perform syntax check I don't get errors, but when I call it from C# I get syntax error near SelFromWeather2.
Here is code:
CREATE PROCEDURE SelFromWeather2
#location VARCHAR(MAX),
#des VARCHAR(200) OUTPUT,
#min INT OUTPUT,
#max INT OUTPUT,
#humidity INT OUTPUT,
#pressure INT OUTPUT,
#speed INT OUTPUT,
#date Datetime OUTPUT
AS
IF EXISTS(SELECT * FROM Weather2 WHERE LOCATION LIKE #location)
BEGIN
CREATE TABLE T
(
forc XML,
loc VARCHAR(MAX),
dat Datetime
);
INSERT INTO T(forc, loc, dat) SELECT TOP 1 [FORECAST],[LOCATION],[DATE] FROM Weather2
WHERE LOCATION LIKE #location ORDER BY DATE DESC;
SET #location=(SELECT loc FROM T);
SET #location =(SELECT loc FROM T);
SET #des= (SELECT forc.value('(/Weather//Forecast/Description/node())[1]', 'nvarchar(max)') FROM T);
SET #min= (SELECT forc.value('(/Weather//Forecast/MinTemp/node())[1]', 'int') FROM T);
SET #max=(SELECT forc.value('(/Weather//Forecast/MaxTemp/node())[1]', 'int') FROM T);
SET #humidity=(SELECT forc.value('(/Weather//Forecast/Humidity/node())[1]', 'int') FROM T);
SET #pressure= (SELECT forc.value('(/Weather//Forecast/Pressure/node())[1]', 'int') FROM T);
SET #speed=(SELECT forc.value('(/Weather//Forecast/Speed/node())[1]', 'int') FROM T);
SET #date= (SELECT forc.value('(/Weather//Forecast/Date/node())[1]', 'Datetime') FROM T);
DROP TABLE T;
END
The code for calling this procedure is:
string location = "Paris";
SqlDataReader myReader = null;
SqlCommand myComand = new SqlCommand("SelFromWeather2", myConnection);
myComand.Parameters.AddWithValue("#location", location);
SqlParameter min = myComand.Parameters.Add("#min", System.Data.SqlDbType.Int);
SqlParameter max = myComand.Parameters.Add("#max", System.Data.SqlDbType.Int);
SqlParameter humidity = myComand.Parameters.Add("#humidity", System.Data.SqlDbType.Int);
SqlParameter pressure = myComand.Parameters.Add("#pressure", System.Data.SqlDbType.Int);
SqlParameter speed = myComand.Parameters.Add("#speed", System.Data.SqlDbType.Int);
SqlParameter dat = myComand.Parameters.Add("#date", System.Data.SqlDbType.DateTime);
SqlParameter des = myComand.Parameters.Add("#des", System.Data.SqlDbType.VarChar, 200);
min.Direction = System.Data.ParameterDirection.Output;
max.Direction = System.Data.ParameterDirection.Output;
humidity.Direction = System.Data.ParameterDirection.Output;
pressure.Direction = System.Data.ParameterDirection.Output;
speed.Direction = System.Data.ParameterDirection.Output;
dat.Direction = System.Data.ParameterDirection.Output;
des.Direction = System.Data.ParameterDirection.Output;
myComand.ExecuteReader();
int minTemp = (int)min.Value;
int maxTemp = (int)max.Value;
int hum = (int)humidity.Value;
int press = (int)pressure.Value;
int wind = (int)speed.Value;
string description = des.Value.ToString();
DateTime datum = (DateTime)dat.Value;
Please help, I'm stuck!
Set CommandType of myCommand to StoredProcedure
You need to set the CommandType to StoredProcedure
myCommand.CommandType = CommandType.StoredProcedure
The default is Text.
I have created a package successfully.
But when I try to call this on my C# program
I am getting an error:
wrong number or types of arguments in call to LOG_STATUS
LOG_STATUS is the name of the procedure:
CREATE OR REPLACE PACKAGE BODY ITMON.SERVERSTATUS AS
PROCEDURE LOG_STATUS(out_RESULT OUT sys_refcursor)
IS
BEGIN
OPEN out_RESULT FOR
SELECT HOSTNAME, USERS, PS_NAME
FROM PS_COLLECT
WHERE NOT EXISTS
(
SELECT HOSTNAME, USERS, PS_NAME
FROM PS_MASTER
WHERE PS_MASTER.HOSTNAME = PS_COLLECT.HOSTNAME
AND PS_MASTER.USERS = PS_COLLECT.USERS
AND PS_MASTER.PS_NAME = PS_COLLECT.PS_NAME
);
END LOG_STATUS;
END;
Here is my C# Code:
OracleCommand OCom = new OracleCommand("SERVERSTATUS.LOG_STATUS", oc);
OCom.CommandType = CommandType.StoredProcedure;
OCom.Parameters.Add("out_RESULT", OracleType.VarChar, 30000).Direction = ParameterDirection.Output;
OCom.Parameters[0].Value = sid;
OracleDataAdapter _daGrid1 = new OracleDataAdapter(OCom);
_daGrid1.Fill(_dsGrid);
I found out what's wrong with my code..
Should change this line:
OCom.Parameters.Add("out_RESULT", OracleType.VarChar, 30000).Direction = ParameterDirection.Output;
to
OCom.Parameters.Add("out_RESULT", OracleType.Cursor).Direction = ParameterDirection.Output;
Should use Cursor instead of varchar..
I have been struggling with this for quite some time having been accustomed to SQL Server. I have the following code and I have verified that the OracleDbType's are correct and have verified that the actual values being passed to the parameters match. I think my problem may rest with the return value. All it does is give me the row count. I read somewhere that the return parameter must be set at the top. The specific error I am getting says,
PLS-00306: wrong number or types of arguments in call to \u0027INSERT_REC\u0027
ORA-06550: line 1, column 7:\nPL/SQL: Statement ignored
The stored procedure is:
PROCEDURE INSERT_REC
(
A_MILL_CENTER IN GRO_OWNER.MOVEMENT.MILL_CENTER%TYPE, --# VARCHAR2(10)
A_INGREDIENT_CODE IN GRO_OWNER.MOVEMENT.INGREDIENT_CODE%TYPE, --# VARCHAR2(50)
A_FEED_CODE IN GRO_OWNER.MOVEMENT.FEED_CODE%TYPE, --# VARCHAR2(30)
--# A_MOVEMENT_TYPE should be ‘RECEIPT’ for ingredient receipts
A_MOVEMENT_TYPE IN GRO_OWNER.MOVEMENT.MOVEMENT_TYPE%TYPE, --# VARCHAR2(10)
A_MOVEMENT_DATE IN VARCHAR2, --# VARCHAR2(10)
A_MOVEMENT_QTY IN GRO_OWNER.MOVEMENT.MOVEMENT_QTY%TYPE, --# NUMBER(12,4)
--# A_INVENTORY_TYPE should be ‘INGREDIENT’ or ‘FINISHED’
A_INVENTORY_TYPE IN GRO_OWNER.MOVEMENT.INVENTORY_TYPE%TYPE, --# VARCHAR2(10)
A_CREATE_USERID IN GRO_OWNER.MOVEMENT.CREATE_USERID%TYPE, --# VARCHAR2(20)
A_RETURN_VALUE OUT NUMBER --# NUMBER(10,0)
);
My code is as follows:
for (int i=0; i < theData.Length -1; i+=3)
{
//3 items hardcoded for now
string millCenter = "0010260510";
string movementType = "RECEIPT";
string feedCode = "test this";
string userID = "GRIMMETTM";
string inventoryType = "INGREDIENT"; //set to FINISHED for feed stuff
string movementDate = theData[i];
string ingCode = System.Text.RegularExpressions.Regex.Match(
theData[i + 1], #"^([0-9]*)").ToString();
//int pounds = Convert.ToInt32(theData[i + 2].Replace(",", ""));
int pounds = 100;
//setup parameters
OracleParameter p9 =
new OracleParameter("A_RETURN_VALUE", OracleDbType.Int32, 30);
p9.Direction = ParameterDirection.ReturnValue;
oraCmd.Parameters.Add(p9);
OracleParameter p1 =
new OracleParameter("A_MILL_CENTER", OracleDbType.Varchar2, 10);
p1.Direction = ParameterDirection.Input;
p1.Value = millCenter;
oraCmd.Parameters.Add(p1);
OracleParameter p2 =
new OracleParameter("A_INGREDIENT_CODE", OracleDbType.Varchar2, 50);
p2.Direction = ParameterDirection.Input;
p2.Value = ingCode;
oraCmd.Parameters.Add(p2);
OracleParameter p3 =
new OracleParameter("A_FEED_CODE", OracleDbType.Varchar2, 30);
p3.Direction = ParameterDirection.Input;
p3.Value = feedCode;
oraCmd.Parameters.Add(p3);
OracleParameter p4 =
new OracleParameter("A_MOVEMENT_TYPE", OracleDbType.Varchar2, 10);
p4.Direction = ParameterDirection.Input;
p4.Value = movementType;
oraCmd.Parameters.Add(p4);
OracleParameter p5 =
new OracleParameter("A_MOVEMENT_DATE", OracleDbType.Varchar2, 10);
p5.Direction = ParameterDirection.Input;
p5.Value = movementDate;
oraCmd.Parameters.Add(p5);
OracleParameter p6 =
new OracleParameter("A_MOVEMENT_QTY", OracleDbType.Int32, 12);
p6.Direction = ParameterDirection.Input;
p6.Value = pounds;
oraCmd.Parameters.Add(p6);
OracleParameter p7 =
new OracleParameter("A_INVENTORY_TYPE", OracleDbType.Varchar2, 10);
p7.Direction = ParameterDirection.Input;
p7.Value = inventoryType;
oraCmd.Parameters.Add(p7);
OracleParameter p8 =
new OracleParameter("A_CREATE_USERID", OracleDbType.Varchar2, 20);
p8.Direction = ParameterDirection.Input;
p8.Value = userID;
oraCmd.Parameters.Add(p8);
//open and execute
oraConn.Open();
oraCmd.ExecuteNonQuery();
oraConn.Close();
ParameterDirection for A_RETURN_VALUE should be ParameterDirection.Output
Have you tried adding the RETURN_VALUE parameter last instead of first? If I recall, parameters have to be in the exact same order when calling an Oracle stored procedure through the Oracle provider.
Can't tell from your sample, but could it be that you are declaring the oraCmd object outside the scope of the for loop? I don't see the declaration in the example, but if this is the case, then each iteration would add all the Oracle Parameters to the array and you would have too many on any runs after the first.