I have inherited a function in an ASP.NET (C#) application where the author used the Microsoft.Practices.EnterpriseLibrary.Data library, but I have been asked to change it so that it uses System.Data.OracleClient. This function uses a stored procedure form a database. itemName, and openDate are string parameters that the function takes in. PKG_AUCTION_ITEMS.IsAuctionItem is the stored procedure function name.
Here is the code that I received:
string result = String.Empty;
Database db = DatabaseFactory.CreateDatabase("OraData");
using (DbCommand cmdDB = db.GetStoredProcCommand("PKG_AUCTION_ITEMS.IsAuctionItem"))
{
db.AddInParameter(cmdDB, "vItemName", DbType.String, itemName);
db.AddInParameter(cmdDB, "vOpenDate", DbType.String, openDate);
db.AddParameter(cmdDB, "ret", DbType.String, 2, ParameterDirection.ReturnValue, false, 0, 0, null, DataRowVersion.Current, null);
db.ExecuteNonQuery(cmdDB);
result = cmdDB.Parameters["ret"].Value.ToString();
}
Here is my code:(connstr is the connection string)
string result = String.Empty;
OracleConnection conn = new OracleConnection(connstr);
OracleCommand cmd = new OracleCommand("PKG_AUCTION_ITEMS.IsAuctionItem",conn);
myCmd.CommandType = CommandType.StoredProcedure;
using (myCmd)
{
myCmd.Parameters.AddWithValue("vItemName", itemName);
myCmd.Parameters.AddWithValue("vOpenDate", openDate);
myCmd.Parameters.AddWithValue("ret", ???);
myCmd.ExecuteNonQuery();
result = myCmd.Parameters["ret"].Value.ToString();
}
I do not understand what the difference between AddInParameter and AddParameter is, and what this line does:
db.AddParameter(cmdDB, "ret", DbType.String, 2, ParameterDirection.ReturnValue, false, 0, 0, null, DataRowVersion.Current, null);
Am I on the right track? Can anyone please help?
Thanks
db.AddParameter adds an output parameter in this case. You need to let the db client library know that you're looking to get the return value back from the sproc call. Hence the call to AddParameter. db.AddInParameter adds a parameter which is only an in-parameter. In the It's a shortcut for db.AddParameter using ParameterDirection.Input. See http://blogs.x2line.com/al/archive/2006/03/25/1579.aspx for a discussion of AddInParameter vs. AddParameter.
Similarly, using OracleClient, AddWithValue is like AddInParameter-- a shortcut to use for input params when you already know the value. Since the return value is, by definition, an output parameter, you can't use AddWithValue. You need to use Parameters.Add() instead.
Now, back to your main question: what's the equivalent code using OracleClient. It's something like this:
string result = String.Empty;
OracleConnection conn = new OracleConnection(connstr);
OracleCommand cmd = new OracleCommand("PKG_AUCTION_ITEMS.IsAuctionItem",conn);
myCmd.CommandType = CommandType.StoredProcedure;
using (myCmd)
{
myCmd.Parameters.AddWithValue("vItemName", itemName);
myCmd.Parameters.AddWithValue("vOpenDate", openDate);
// depending on whether you're using Microsoft's or Oracle's ODP, you
// may need to use OracleType.Varchar instead of OracleDbType.Varchar2.
// See http://forums.asp.net/t/1002097.aspx for more details.
OracleParameter retval = new OracleParameter("ret",OracleDbType.Varchar2,2);
retval.Direction = ParameterDirection.ReturnValue;
myCmd.Parameters.Add(retval);
myCmd.ExecuteNonQuery();
result = myCmd.Parameters["ret"].Value.ToString();
}
We actually do the configuration of the parameters more explicitly, something like this
System.Data.OracleClient.OracleCommand command = new System.Data.OracleClient.OracleCommand("PACKAGE_NAME.STORED_NAME");
command.CommandType = System.Data.CommandType.StoredProcedure;
System.Data.OracleClient.OracleParameter param;
param = new System.Data.OracleClient.OracleParameter("PARAM_NAME_ID", System.Data.OracleClient.OracleType.Number);
param.Value = id;
command.Parameters.Add(param);
param = new System.Data.OracleClient.OracleParameter("PARAM_NAME_RETURN_COUNT", System.Data.OracleClient.OracleType.Number);
param.Direction = System.Data.ParameterDirection.Output;
command.Parameters.Add(param);
...
You see, there is a property direction which we explicitly assign for the parameter that is being returned. The first gets the value of a variable "id" and is a parameter that gets passed TO the stored procedure.
The 2nd one is being returned by the stored procedure, therefore no value is assigned to that parameter value and the direction is set to "System.Data.ParameterDirection.Output"
Related
I have a stored procedure created with a static variable (#Location).
Im trying to create a C# app that will pass the LocationID parameter to the stored procedure. The parameters will need to be passed TWICE (Location1 and Location2). So far all I have is the following code, and I'm not sure how to loop it, or if its written properly?
using (Conn)
{
SqlCommand cmd = new SqlCommand("[dbo].[sp_EXAMPLESPROC]",Conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter LocationParam = cmd.Parameters.AddWithValu("#LocationID", "1");
LocationParam.SqlDbType = SqlDbType.Structured;
Let's say you put your code into a method called StoreLocation(). You'd make it take a parameter `locationId' (is it really a string like you have?) like so:
private void StoreLocation(string locationId)
{
using (Conn)
{
SqlCommand cmd = new SqlCommand("[dbo].[sp_EXAMPLESPROC]",Conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter LocationParam = cmd.Parameters.AddWithValue("#LocationID", locationId);
LocationParam.SqlDbType = SqlDbType.Structured;
cmd.ExecuteNonQuery(); // Or however your sproc works.
}
}
Then you just call it twice or use a loop or whatever you want:
private void SomeCallerMethod()
{
// Whatever other code you have.
StoreLocation("1");
StoreLocation("2");
// More other code.
}
add LocationID1 and LocationID2 parameters to stored procedures and then
do like this
cmd.Parameters.Add(#LocationID1", SqlDbType.VarChar).Value = "1";
cmd.Parameters.Add(#LocationID2", SqlDbType.VarChar).Value = "2";
this should work
I am fairly new to C# and I'm trying to set up call to a stored procedure in my database which takes one parameter.
I get the error "Procedure or function 'SP_getName' expects parameter '#username', which was not supplied. "
My Stored procedure works ok when I supply it with the parameter and I run it via SQL management studio.
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[SP_getName]
#username = 'bob101'
SELECT 'Return Value' = #return_value
GO
However when I try and call it the error is with how I'm passing the parameter in, but I can't spot what the issue is.
//create a sql command object to hold the results of the query
SqlCommand cmd = new SqlCommand();
//and a reader to process the results
SqlDataReader reader;
//Instantiate return string
string returnValue = null;
//execute the stored procedure to return the results
cmd.CommandText = "SP_getName";
//set up the parameters for the stored procedure
cmd.Parameters.Add("#username", SqlDbType.NVarChar).Value = "bob101";
cmd.CommandType = CommandType.Text;
cmd.Connection = this.Connection;
// then call the reader to process the results
reader = cmd.ExecuteReader();
Any help in spotting my error would be greatly appreciated!
I've also tried looking at these two posts, but I haven't had any luck:
Stored procedure or function expects parameter which is not supplied
Procedure or function expects parameter, which was not supplied
Thanks!
You have stated:
cmd.CommandType = CommandType.Text;
Therefore you are simply executing:
SP_getName
Which works because it is the first statement in the batch, so you can call the procedure without EXECUTE, but you aren't actually including the parameter. Change it to
cmd.CommandType = CommandType.StoredProcedure;
Or you can change your CommandText to:
EXECUTE SP_getName #username;
As a side note you should Avoid using the prefix 'sp_' for your stored procedures
And a further side note would be to use using with IDisposable objects to ensure they are disposed of correctly:
using (var connection = new SqlConnection("ConnectionString"))
using (var cmd = new new SqlCommand("SP_getName", connection))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#username", SqlDbType.NVarChar).Value = "bob101";
connection.Open();
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
// Do something
}
}
}
I had this problem, but it wasn't about parameter name of Command Type.
My problem was that when C# calls SP, for each parameter that has no value passes 'default' keyword (i found it in SQL Profiler):
... #IsStop=0,#StopEndDate=default,#Satellite=0, ...
in my case my parameter Type was DateTime :
#StopEndDate datetime
. I Solved my problem by seting default value to this parameter in Stored Procedure :
#StopEndDate datetime=null
Try remove #:
cmd.Parameters.Add("username", SqlDbType.NVarChar).Value = "bob101";
I have a web service in C#, I use it to consults from tables, but I want to create a WebMethod to call a stored procedure and get back multiples output parameters. I can execute it with output parameters, it doesn't work when I try to call it whit outputs parameters.
This is a sample, I want to get back more that 2 parameters.
Stored procedure:
CREATE OR REPLACE PROCEDURE O_CAPEREZ.GIO_SP (
VNOMBRE IN VARCHAR2,
SALUDO OUT VARCHAR2 )
AS
BEGIN
INSERT INTO G_PRUEBA_SP(NOMBRE)
VALUES (vNOMBRE);
SALUDO:= ('Hello: ' || vNOMBRE);
END;
And this is my code in the web service, when I execute it using output variables I get this error
[HYC00] [Oracle][ODBC]Optional feature not implemented
C# code:
[WebMethod]
public string AP_Data(string curp)
{
string constr = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
using (OdbcConnection con = new OdbcConnection(constr))
{
OdbcCommand cmd = new OdbcCommand("{CALL GIO_SP(?,?)}", con);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#vNOMBRE", (curp));
cmd.Parameters.Add("#vNOMBRE", OdbcType.VarChar, 18);
cmd.Connection.Open();
cmd.ExecuteNonQuery();
cmd.Parameters["#SALUDO"].Direction = ParameterDirection.ReturnValue;
cmd.Connection.Close();
string ret = Convert.ToString(cmd.Parameters["#SALUDO"].Value);
return ret;
}
}
You have to add the parameter to the list even if you're not going to set a value there:
cmd.Parameters.Add("#SALUDO", OdbcType.VarChar, 18).Direction = ParameterDirection.Output;
I don't know the the Oracle flavor is different, but in SQL I use ParameterDirection.ReturnValue rather than ParameterDirection.Output.
here's how i do it in MS SQL server 2008 But notice the data type and the lenth of the variables your create must be the same in your table
the stored proc create code
USE DATABASE DATABASE_NAME
GO
CREATE PROC SP_METHOD
#ID_CATIGORY INT,
#NAME VARCHAR (50),
#DESCRIPTION VARCHAR (50)
AS
INSERT INTO TABLE_NAME
([ID_CAT]
,[NAME_PRODUCT]
,[DESC_PRODUCT]
)
VALUES
( #ID_CATIGORY
,#NAME
,#DESCRIPTION )
GO
in the c# code
// Create SqlConnection
SqlConnection conn= new SqlConnection(#"Server=server_name;
DataBase=your_data_base_name;Integrated Security=false;User
Id=user_id;Password=password");
// Open the Connection
if (sqlconnection.State != ConnectionState.Open)
{
conn= .Open();
}
// execute stored_procedure method don't change this
public void ExecuteCommand(string stored_procedure, SqlParameter[] param)
{
SqlCommand sqlcomd = new SqlCommand();
sqlcomd.CommandType = CommandType.StoredProcedure;
sqlcomd.CommandText = stored_procedure;
sqlcomd.Connection = sqlconnection;
if (param !=null)
{
sqlcomd.Parameters.AddRange(param);
}
sqlcomd.ExecuteNonQuery();
}
// close connection method
public void close_conn()
{
if (sqlconnection.State == ConnectionState.Open)
{
sqlconnection.Close();
}
}
// execute and retrieving data Method
public void Add_product(int ID_cat ,string Name_Product,string
Des_Product)
{
SqlParameter[] param = new SqlParameter[3];
param[0] = new SqlParameter("#ID_CAT", SqlDbType.Int);
param[0].Value = ID_cat;
param[1] = new SqlParameter("#NAME_PRODUCT", SqlDbType.VarChar, 50);
param[1].Value = Name_Product;
param[2] = new SqlParameter("#DESC_PRODUCT", SqlDbType.VarChar, 50);
param[2].Value = Des_Product;
ExecuteCommand("StoredProcedure_name", param);
close_conn();
}
and finally you can call this function
Add_product(Convert.ToInt32(ComboBox.SelectedValue),txt_name.Text,
txt_desc.Text);
if there is any part you don't understand lemme know
I've seen many ways to accomplish this.
One way is to Pipe Delimit your select statement in your stored procedure and then use "Value1|Value2".Split('|')[0] to get Value1.
You could also return a table instead of using multiple parameters
DataTable table = new DataTable();
DataAdapter adapter = new DataAdapter(cmd);
adapter.fill(table);
return table.Rows[0]["Greeting"] + table.Rows[0]["Name"];
In the second example you can return as many 'Parameters' as you want, but you will have to assign them to their rightful spots later in your code.
I've also seen an XML way to do this same feature but I won't provide the code here since I don't personally think it is a very good way to do it. The way I've seen done was adding a bunch of XML attributes to a parent tag, and then coming back later and finding the value of each tag later in the code.
In MYSQL it would go like this
CREATE PROCEDURE O_CAPEREZ.GIO_SP (
#vNOMBRE VARCHAR(50))
AS
BEGIN
INSERT INTO G_PRUEBA_SP(NOMBRE)
VALUES (#vNOMBRE);
select 'Hola' as Greeting, #vNOMBRE as Name
END
Also note what Marc_s commented
You need to set the .Direction of the parameter BEFORE making the call to .ExecuteNonQuery()
I am getting a SqlException
Procedure or function 'GetDashboardData' expects parameter '#userID', which was not supplied.
I have been trying to follow this post, however does not seem to cater for passing parameters.
https://msdn.microsoft.com/en-us/data/jj691402.aspx and then looked for fixes
I have then continued to try and pass it a parameter but got this exception thrown (shown above) and googled around. I have tried the first answer post in this post as it seems the most relevant and quickest way
Passing parameter to Stored Procedure using DbContext
However this did not work so was wondering how do I go about passing this parameter?
string userID = User.Identity.GetUserId();
// If using code first we need to make sure the model built before we open a connection
db.Database.Initialize(force: false);
var command = db.Database.Connection.CreateCommand();
command.CommandText = "[dbo].[GetDashboardData]";
var userIDParameter = new SqlParameter { ParameterName = "#userID", Value = userID, DbType = DbType.String, Direction = ParameterDirection.Input };
command.Parameters.Add(userIDParameter);
try
{
db.Database.Connection.Open();
// We now run the stored procedure
var reader = command.ExecuteReader();
var getUserDashboards = ((IObjectContextAdapter)db).ObjectContext.Translate<DashboardModel>(reader, "DashboardModel", MergeOption.AppendOnly);
}
finally
{
db.Database.Connection.Close();
}
I have a function in Oracle that returns a sequence number. When I try to get that value in C# by a parameter it always tells me that the parameter type is invalid. A sample value of that returned value is 115545. If indeed this error is correct then what is the correspondent in ODBCType for this value? If it isn't correct then what is the problem?
Oracle function is:
FUNCTION Get_Next_Message_Id__
RETURN NUMBER IS
temp_ NUMBER;
CURSOR get_in_message_id_seq IS
SELECT in_message_id_seq.NEXTVAL
FROM dual;
BEGIN
General_SYS.Init_Method(lu_name_, 'IN_MESSAGE_API', 'Get_Next_Message_Id__', TRUE);
OPEN get_in_message_id_seq;
FETCH get_in_message_id_seq INTO temp_;
CLOSE get_in_message_id_seq;
RETURN(temp_);
END Get_Next_Message_Id__;
C# Code:
OdbcConnection myConnection = new OdbcConnection(ODBC_CLass.ifsconnectionstring);
OdbcParameter next_id = new OdbcParameter();
next_id.Direction = ParameterDirection.Output;
myConnection.Open();
OdbcCommand command = new OdbcCommand("{? = call ifsapp.in_message_api.Get_Next_Message_Id__}", myConnection);
command.CommandType = CommandType.StoredProcedure;
next_id = command.Parameters.Add("temp_", OdbcType.Int);
int k = command.ExecuteNonQuery();
MessageBox.Show("next_id: " + next_id.Value);
I believe the problem is in the way you're setting next_id. You're first creating an OdbcParameter and setting its direction - but then completely ignoring it, and reassigning the variable using the Add method, which will be creating an "in" parameter by default. Try this instead:
OdbcParameter nextId = command.Parameters.Add("temp_", OdbcType.Int);
nextId.Direction = ParameterDirection.Output;
Note that you should also be using using statements for the connection and command, to ensure they're cleaned up at the end of the code, whatever happens.