How to Handle SQL Exception Must Pass Parameter number 'x'? - c#

I am trying to store Binary Data by using store procedure. Store procedure has three parameters. Last parameter will be containing Binary Data. But when I run a code it gives SQL Exception
Must pass parameter number 3 and subsequent parameters as '#name =
value'. After the form '#name = value' has been used, all subsequent
parameters must be passed in the form '#name = value'.
SqlCommand cmd = new SqlCommand("EXEC myProc #param1 = 8, #param2= '5.png', #FileSignature");
using (SqlConnection conn = new SqlConnection(myConnString))
{
cmd.Connection = conn;
if (FileSignature == null) //FileSignature is byte[]
{
cmd.Parameters.Add("#FileSignature", SqlDbType.VarBinary, -1);
cmd.Parameters["#FileSignature"].Value = System.DBNull.Value;
}
else
cmd.Parameters.AddWithValue("#FileSignature", FileSignature); //FileSignature is byte[]
int iReturn = cmd.ExecuteNonQuery();
}

You can't use #param=val for some parameters and #param for others.
Also, this is not the proper way to execute a stored procedure using sqlCommand.
Please try reading the exception message. It's plain english and is there to help.
Try this:
using(SqlConnection conn = new SqlConnection(myConnString),
SqlCommand cmd = new SqlCommand("myProc", conn)
{
cmd.CommandType = SqlCommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#param1", 8);
cmd.Parameters.AddWithValue("#param2", '5.png');
if (FileSignature == null) //FileSignature is byte[]
{
cmd.Parameters.Add("#FileSignature", SqlDbType.VarBinary, -1);
cmd.Parameters["#FileSignature"].Value = System.DBNull.Value;
}
else
{
cmd.Parameters.AddWithValue("#FileSignature", FileSignature); //FileSignature is byte[]
}
conn.Open();
int iReturn = cmd.ExecuteNonQuery();
conn.Close();
}

Because you supplied the first two parameters by name you must do so for all three. So you need to update you SqlCommand text to include it SqlCommand cmd = new SqlCommand("EXEC myProc #param1 = 8, #param2= '5.png', **#Parameter3** = #FileSignature");
Replace #Parameter3 with the name from your Stored Proc or optional you could just not pass any names (as long as the parameters are in the same order in your procedure.
SqlCommand cmd = new SqlCommand("EXEC myProc 8, '5.png', #FileSignature");

Related

Stored procedure expects parameter but parameter is actually supplied?

I need to know why I am still getting this error
Stored procedure expects parameter which was not supplied
But I am actually sending this parameter.
The stored procedure in the database looks like this:
CREATE PROCEDURE SVC_BUSCA_MEDIO_LANDING
(#rut VARCHAR)
AS
BEGIN
SELECT utm_source
FROM landing_formulario
WHERE rut = #rut
END
And my .net code:
string result = string.Empty;
string connString = System.Configuration.ConfigurationManager.AppSettings["StPazWeb"].ToString();
string SVC_BUSCA_MEDIO_LANDING = "SVC_BUSCA_MEDIO_LANDING";
using (SqlConnection connection = new SqlConnection(connString))
{
connection.Open();
try
{
SqlCommand command = new SqlCommand(SVC_BUSCA_MEDIO_LANDING);
command.CommandType = CommandType.StoredProcedure;
command = new SqlCommand(command.CommandText, connection);
command.Parameters.AddWithValue("#rut", rut);
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
result = (string)reader["utm_source"];
}
}
catch (SqlException ex)
{
throw new Exception("Oops!." + ex.Message);
}
}
return result.ToString();
Any idea what can be happening?
For some reason you create the command twice, with the second instantiation replacing the first, however on the second one you don't set the command type, and as a result your parameter is being ignored.
Try:
SqlCommand command = connection.CreateCommand();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = SVC_BUSCA_MEDIO_LANDING;
command.Parameters.AddWithValue("#rut", rut);
You're using:
SqlCommand command = new SqlCommand(SVC_BUSCA_MEDIO_LANDING);
but you're reseting the command at:
command = new SqlCommand(command.CommandText, connection);
Try instead:
SqlCommand command = new SqlCommand();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "SVC_BUSCA_MEDIO_LANDING";
command = new SqlCommand(command.CommandText, connection);
command.Parameters.AddWithValue("#rut", rut);

SQLCLR stored procedures with input parameter

I am quite new to SQLCLR stored procedures. In my example I have two stored procedures, one without a parameter and one with a input parameter. Both target the same tables.
The one without the parameter is working fine and returns all rows in the result. But the one with an input parameter targeting the same tables is not returning any rows even though I am not receiving any errors. The input parameter in the .NET code is set as SqlString and in the database is NVARCHAR(50).
This is how my C# code looks:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void AirlineSqlStoredProcedure (SqlString strAirline)
{
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "Context Connection=true";
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
conn.Open();
cmd.CommandText = "SELECT dbo.tblAirline.AirlineName, dbo.tblAircraft.AircraftUnits, dbo.tblAircraft.Manufacturer, dbo.tblAircraft.AircraftModel FROM dbo.tblAircraft INNER JOIN dbo.tblAirline ON dbo.tblAircraft.AirlineID = dbo.tblAirline.AirlineID WHERE AirlineName = '#strAirline' ORDER BY dbo.tblAircraft.AircraftUnits DESC";
SqlParameter paramAge = new SqlParameter();
paramAge.Value = strAirline;
paramAge.Direction = ParameterDirection.Input;
paramAge.SqlDbType = SqlDbType.NVarChar;
paramAge.ParameterName = "#strAirline";
cmd.Parameters.Add(paramAge);
SqlDataReader sqldr = cmd.ExecuteReader();
SqlContext.Pipe.Send(sqldr);
sqldr.Close();
conn.Close();
}
[Microsoft.SqlServer.Server.SqlProcedure]
public static void AirlineAircraftStoredProcedure()
{
//It returns rows from Roles table
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "Context Connection=true";
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT dbo.tblAirline.AirlineName, dbo.tblAircraft.AircraftUnits, dbo.tblAircraft.Manufacturer, dbo.tblAircraft.AircraftModel FROM dbo.tblAircraft INNER JOIN dbo.tblAirline ON dbo.tblAircraft.AirlineID = dbo.tblAirline.AirlineID ORDER BY dbo.tblAircraft.AircraftUnits DESC";
conn.Open();
SqlDataReader sqldr = cmd.ExecuteReader();
SqlContext.Pipe.Send(sqldr);
sqldr.Close();
conn.Close();
}
}
And when I execute the stored procedure I get empty rows:
USE [TravelSight]
GO
DECLARE #return_value Int
EXEC #return_value = [dbo].[AirlineSqlStoredProcedure]
#strAirline = N'American Airlines'
SELECT #return_value as 'Return Value'
GO
(0 row(s) affected)
(1 row(s) affected)
Also, for the input parameter I put an N before the string.
When running the stored procedure AirlineAircraftStoredProcedure targeting the same tables, I am getting all the rows back:
USE [TravelSight]
GO
DECLARE #return_value Int
EXEC #return_value = [dbo].[AirlineAircraftStoredProcedure]
SELECT #return_value as 'Return Value'
GO
(8 row(s) affected)
(1 row(s) affected)
What have I done wrong here?
Two (maybe 3) problems:
paramAge.Value = strAirline; should be:
paramAge.Value = strAirline.Value;
Notice the use of the .Value property.
WHERE AirlineName = '#strAirline' (within cmd.CommandText = "... ) should be:
WHERE AirlineName = #strAirline
Notice that the single-quotes were removed in the query text. You only use single-quotes for literals and not parameters / variables.
Replace the following 5 lines:
SqlParameter paramAge = new SqlParameter();
paramAge.Value = strAirline;
paramAge.Direction = ParameterDirection.Input;
paramAge.SqlDbType = SqlDbType.NVarChar;
paramAge.ParameterName = "#strAirline";
with:
SqlParameter paramAge = new SqlParameter("#strAirline", SqlDbType.NVarChar, 50);
paramAge.Direction = ParameterDirection.Input; // optional as it is the default
paramAge.Value = strAirline.Value;
Please note that the "size" parameter was set in the call to new SqlParameter(). It is important to always specify max string lengths.
With the technical problem out of the way, there are two larger issues to address:
Why is this being done in SQLCLR in the first place? Nothing specific to .NET is being done. Based solely on the code posted in the Question, this would be much better off as a regular T-SQL Stored Procedure.
If it must remain in SQLCLR, then you really need to wrap the disposable objects in using() constructs, namely: SqlConnection, SqlCommand, and SqlDataReader. For example:
using (SqlConnection conn = new SqlConnection("Context Connection=true"))
{
using (SqlCommand cmd = conn.CreateCommand())
{
...
}
}
and then you do not need the following two lines:
sqldr.Close();
conn.Close();
as they will be called implicitly by the call to each of their Dispose() methods.

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;

Calling stored procedure with return value

I am trying to call a stored procedure from my C# windows application. The stored procedure is running on a local instance of SQL Server 2008. I am able to call the stored procedure but I am not able to retrieve the value back from the stored procedure. This stored procedure is supposed to return the next number in the sequence. I have done research online and all the sites I've seen have pointed to this solution working.
Stored procedure code:
ALTER procedure [dbo].[usp_GetNewSeqVal]
#SeqName nvarchar(255)
as
begin
declare #NewSeqVal int
set NOCOUNT ON
update AllSequences
set #NewSeqVal = CurrVal = CurrVal+Incr
where SeqName = #SeqName
if ##rowcount = 0 begin
print 'Sequence does not exist'
return
end
return #NewSeqVal
end
Code calling the stored procedure:
SqlConnection conn = new SqlConnection(getConnectionString());
conn.Open();
SqlCommand cmd = new SqlCommand(parameterStatement.getQuery(), conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter param = new SqlParameter();
param = cmd.Parameters.Add("#SeqName", SqlDbType.NVarChar);
param.Direction = ParameterDirection.Input;
param.Value = "SeqName";
SqlDataReader reader = cmd.ExecuteReader();
I have also tried using a DataSet to retrieve the return value with the same result. What am I missing to get
the return value from my stored procedure? If more information is needed, please let me know.
You need to add a ReturnValue-direction parameter to the command:
using (SqlConnection conn = new SqlConnection(getConnectionString()))
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = parameterStatement.getQuery();
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("SeqName", "SeqNameValue");
// #ReturnVal could be any name
var returnParameter = cmd.Parameters.Add("#ReturnVal", SqlDbType.Int);
returnParameter.Direction = ParameterDirection.ReturnValue;
conn.Open();
cmd.ExecuteNonQuery();
var result = returnParameter.Value;
}
Setting the parameter's direction to ParameterDirection.ReturnValue instructs the SqlCommand to declare it as a variable and assign the stored procedure's return value to it (exec #ReturnValue = spMyProcedure...), exactly like you would write it in SQL.
I know this is old, but i stumbled on it with Google.
If you have a return value in your stored procedure say "Return 1" - not using output parameters.
You can do the following - "#RETURN_VALUE" is silently added to every command object. NO NEED TO EXPLICITLY ADD
cmd.ExecuteNonQuery();
rtn = (int)cmd.Parameters["#RETURN_VALUE"].Value;
The version of EnterpriseLibrary on my machine had other parameters.
This was working:
SqlParameter retval = new SqlParameter("#ReturnValue", System.Data.SqlDbType.Int);
retval.Direction = System.Data.ParameterDirection.ReturnValue;
cmd.Parameters.Add(retval);
db.ExecuteNonQuery(cmd);
object o = cmd.Parameters["#ReturnValue"].Value;
I had a similar problem with the SP call returning an error that an expected parameter was not included. My code was as follows.
Stored Procedure:
#Result int OUTPUT
And C#:
SqlParameter result = cmd.Parameters.Add(new SqlParameter("#Result", DbType.Int32));
result.Direction = ParameterDirection.ReturnValue;
In troubleshooting, I realized that the stored procedure was ACTUALLY looking for a direction of "InputOutput" so the following change fixed the problem.
r
Result.Direction = ParameterDirection.InputOutput;
This is a very short sample of returning a single value from a procedure:
SQL:
CREATE PROCEDURE [dbo].[MakeDouble] #InpVal int AS BEGIN
SELECT #InpVal * 2; RETURN 0;
END
C#-code:
int inpVal = 11;
string retVal = "?";
using (var sqlCon = new SqlConnection(
"Data Source = . ; Initial Catalog = SampleDb; Integrated Security = True;"))
{
sqlCon.Open();
retVal = new SqlCommand("Exec dbo.MakeDouble " + inpVal + ";",
sqlCon).ExecuteScalar().ToString();
sqlCon.Close();
}
Debug.Print(inpVal + " * 2 = " + retVal);
//> 11 * 2 = 22
ExecuteScalar(); will work, but an output parameter would be a superior solution.
You can try using an output parameter. http://msdn.microsoft.com/en-us/library/ms378108.aspx
Or if you're using EnterpriseLibrary rather than standard ADO.NET...
Database db = DatabaseFactory.CreateDatabase();
using (DbCommand cmd = db.GetStoredProcCommand("usp_GetNewSeqVal"))
{
db.AddInParameter(cmd, "SeqName", DbType.String, "SeqNameValue");
db.AddParameter(cmd, "RetVal", DbType.Int32, ParameterDirection.ReturnValue, null, DataRowVersion.Default, null);
db.ExecuteNonQuery(cmd);
var result = (int)cmd.Parameters["RetVal"].Value;
}
I see the other one is closed. So basically here's the rough of my code. I think you are missing the string cmd comment. For example if my store procedure is call:DBO.Test. I would need to write cmd="DBO.test". Then do command type equal to store procedure, and blah blah blah
Connection.open();
String cmd="DBO.test"; //the command
Sqlcommand mycommand;

How to call a mySQL stored function in C#?

I'd like to call a stored function in C#. I need articles and some examples for this.
It's almost identical to how you would call a SQL Server Stored Procedure:
using(MySqlConnection conn = new MySqlConnection(connString))
{
MySqlCommand command = new MySqlCommand("spSomeProcedure;", conn);
command.CommandType = System.Data.CommandType.StoredProcedure;
// Add your parameters here if you need them
command.Parameters.Add(new MySqlParameter("someParam", someParamValue));
conn.Open();
int result = (int)command.ExecuteScalar();
}
http://forums.asp.net/p/988462/1278686.aspx
MySqlCommand cmd = new MySqlCommand("DeleteMessage", new MySqlConnection(GetConnectionString()));
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new MySqlParameter("param1", MessageItem.Entry_ID));
cmd.Connection.Open();
int i = cmd.ExecuteNonQuery();
cmd.Connection.Close();
Stored routines
Stored functions and stored procedures are called in different ways.
Stored function is used as regular function in SQL statement.
For example
SELECT id, title, my_function(price) FROM table
Stored procedures are called using CALL statement.
CALL my_procedure(1,2,'title');
I don't know C#, so probably you can use MySqlCommand class to call stored procedures, but you can't use it to call stored functions.
I actually couldn't get the other methods suggested to return a value. I ended up creating a string to call the function and then executed that string with .ExecuteScalar:
MySqlTransaction mySqlTransaction = testDataMySqlConnection.BeginTransaction();
mySqlCommand = new MySqlCommand
{
Connection = testDataMySqlConnection,
CommandText = "SELECT sf_UnitsAttempted('" + ... + ");",
CommandType = CommandType.Text
};
var f = (float)mySqlCommand.ExecuteScalar();
mySqlCommand.Dispose();
return f;
I know the question is about returning from a stored function, and Justin's answer here covers that. I wanted to add that if you wanted to return a DataTable from a stored procedure instead, you can do it using a DataAdapter:
// using MySql.Data.MySqlClient; // remember to include this
/* Helper method that takes in a Dictionary list of parameters,
and returns a DataTable.
The connection string is fetched from a resources file. */
public static DataTable ExecuteProc(string procedureName, Dictionary<string,object> parameterList)
{
DataTable outputDataTable;
using (MySqlConnection MySqlConnection = new MySqlConnection(Resources.SQL_CONNECTION_STRING))
{
using (MySqlCommand sqlCommand = new MySqlCommand(procedureName, MySqlConnection))
{
sqlCommand.CommandType = CommandType.StoredProcedure;
if (parameterList != null)
{
foreach(string key in parameterList.Keys)
{
string parameterName = key;
object parameterValue = parameterList[key];
sqlCommand.Parameters.Add(new MySqlParameter(parameterName, parameterValue));
}
}
MySqlDataAdapter sqlDataAdapter = new MySqlDataAdapter(sqlCommand);
DataSet outputDataSet = new DataSet();
sqlDataAdapter.Fill(outputDataSet, "resultset");
outputDataTable = outputDataSet.Tables["resultset"];
}
}
return outputDataTable;
}

Categories