Does anyone know how can I read the output variable from .net c#?
Example:
If I have the following stored proc which will return the output variables (#customer_id, #customer_name, #customer_address, #customer_age) instead of the select variable, how can I read the output variable with the following?
mySqlCommand.CommandText = "EXEC app_customers #name=" + sName.Text;
mySqlConnection.Open();
SqlDataReader mySqlDataReader = mySqlCommand.ExecuteReader();
while (mySqlDataReader.Read())
{
}
When the result is a single value (or if you're just interested in the first value in the first column), use the method ExecuteScalar.
It returns an object, simply cast it to the expected type.
int id = (int)mySqlCommand.ExecuteScalar();
Note: the way you're invoking a procedure is not the normal way to do it. Set the command to reference the stored procedure, then add appropriate parameters to the command.Parameters collection. Invoking the procedure using "exec ..." is not a best practice and may even leave you vulnerable. If you need more info on executing such a call, start here.
Edit:
If it is truly an output parameter you need to capture (I believe I misread your question), then the above paragraph is even more applicable. Consider this approach:
mySqlCommand.CommandText = "app_customers";
mySqlCommand.CommandType = System.Data.CommandType.StoredProcedure;
mySqlCommand.Parameters.AddWithValue("#name", theValue);
var customerIdParam = mySqlCommand.Parameters.Add("#customer_id", System.Data.SqlDbType.Int);
customerIdParam.Direction = System.Data.ParameterDirection.Output;
// add more parameters, setting direction as appropriate
mySqlCommand.ExecuteNonQuery();
int customerId = (int)customerIdParam.Value;
// read additional outputs
Related
I am new to writing Stored Procedure. So I wrote one with output parameters and want to access the output value, hot to do it.
My Stored Procedure:
ALTER PROCEDURE selQuery
(
#id int, #code varchar(50) OUTPUT
)
AS
SELECT RecItemCode = #code, RecUsername from Receipt where RecTransaction = #id
RETURN #code
If trying to set "#code=RecItemCode" getting error as : "A SELECT statement that assigns a value to a variable must not be combined with Data Retrieval operations."
And I am using the Stored Procedure as:
con.Open();
cmd.Parameters.AddWithValue("#id", textBox1.Text);
SqlParameter code = new SqlParameter("#code", SqlDbType.Int);
code.Direction = ParameterDirection.Output;
cmd.Parameters.Add(code);
SqlDataReader sdr = cmd.ExecuteReader();
MessageBox.Show(cmd.Parameters["#code"].Value.ToString()); // getting error
con.Close();
Error : "Object reference not set to an instance of an object."
I want to get the value of output parameter. How to get that?
Thanks.
There are a several things you need to address to get it working
The name is wrong its not #ouput its #code
You need to set the parameter direction to Output.
Don't use AddWithValue since its not supposed to have a value just you Add.
Use ExecuteNonQuery if you're not returning rows
Try
SqlParameter output = new SqlParameter("#code", SqlDbType.Int);
output.Direction = ParameterDirection.Output;
cmd.Parameters.Add(output);
cmd.ExecuteNonQuery();
MessageBox.Show(output.Value.ToString());
The SQL in your SP is wrong. You probably want
Select #code = RecItemCode from Receipt where RecTransaction = #id
In your statement, you are not setting #code, you are trying to use it for the value of RecItemCode. This would explain your NullReferenceException when you try to use the output parameter, because a value is never assigned to it and you're getting a default null.
The other issue is that your SQL statement if rewritten as
Select #code = RecItemCode, RecUsername from Receipt where RecTransaction = #id
It is mixing variable assignment and data retrieval. This highlights a couple of points. If you need the data that is driving #code in addition to other parts of the data, forget the output parameter and just select the data.
Select RecItemCode, RecUsername from Receipt where RecTransaction = #id
If you just need the code, use the first SQL statement I showed you. On the offhand chance you actually need the output and the data, use two different statements
Select #code = RecItemCode from Receipt where RecTransaction = #id
Select RecItemCode, RecUsername from Receipt where RecTransaction = #id
This should assign your value to the output parameter as well as return two columns of data in a row. However, this strikes me as terribly redundant.
If you write your SP as I have shown at the very top, simply invoke cmd.ExecuteNonQuery(); and then read the output parameter value.
Another issue with your SP and code. In your SP, you have declared #code as varchar. In your code, you specify the parameter type as Int. Either change your SP or your code to make the types consistent.
Also note: If all you are doing is returning a single value, there's another way to do it that does not involve output parameters at all. You could write
Select RecItemCode from Receipt where RecTransaction = #id
And then use object obj = cmd.ExecuteScalar(); to get the result, no need for an output parameter in the SP or in your code.
You need to define the output parameter as an output parameter in the code with the ParameterDirection.Output enumeration. There are numerous examples of this out there, but here's one on MSDN.
SqlCommand yourCommand = new SqlCommand();
yourCommand.Connection = yourSqlConn;
yourCommand.Parameters.Add("#yourParam");
yourCommand.Parameters["#yourParam"].Direction = ParameterDirection.Output;
// execute your query successfully
int yourResult = yourCommand.Parameters["#yourParam"].Value;
You need to close the connection before you can use the output parameters.
Something like this
con.Close();
MessageBox.Show(cmd.Parameters["#code"].Value.ToString());
private void btnGo_Click(object sender, EventArgs e)
{
Array IDlist = txtUserID.Text.Split(new char[] { });
ArrayList badID = new ArrayList();
foreach (string textLine in IDlist)
{
try
{
int LineID = Convert.ToInt32(textLine);
string emp = txtDistricts.Text;
command.Parameters.Add("#EmpID", SqlDbType.Int).Value = LineID;
if (!emp.Equals(string.Empty))
command.Parameters.Add("#SchoolDistricts", SqlDbType.NVarChar).Value = emp;
else command.Parameters.Add("#SchoolDistricts", SqlDbType.NVarChar).Value = DBNull.Value;
if (cbRemove.Checked)
command.Parameters.Add("#Options", SqlDbType.Int).Value = 1;
else if (cbReset.Checked)
command.Parameters.Add("#Options", SqlDbType.Int).Value = 0;
else command.Parameters.Add("#Options", SqlDbType.Int).Value = DBNull.Value;
SqlParameter returnValue = new SqlParameter("#return_value", DbType.String);
returnValue.Direction = ParameterDirection.ReturnValue;
command.Parameters.Add(returnValue);
conn.Open();
command.Connection = conn;
// command.ExecuteNonQuery();
command.ExecuteScalar();
String OutPutCheck = (command.Parameters["#return_value"].Value.ToString());
String getCheck = (command.ExecuteScalar().ToString());
OPBox.Text += LineID + "--->>" + OutPutCheck + "--->>" + getCheck + "\n";
conn.Close();
//flagUser(LineID, emp);
}
catch (Exception ex)
{
//stored procedure error
badID.Add(textLine);
conn.Close();
}
}}
I made an APP , which takes bunch of ID at a time. After btn_click these values put in array. Then from array each ID pass to store procedure one by one, and get return value. well First value give return value, but after that when second value pass to store procedure it gives following error.
> ERROR::::ex = {"Procedure or function
> usp_Flag_Employee has too many
> arguments specified."}
You keep adding parameters to your command object without reseting it. You should move your connection and command objects into the method where they are being called and use 'using' statements.
Because your connection and command are class fields, each instance of the loop is re-adding the parameters to the old set of parameters. At minimum, reset the parameters collection at the top of the loop.
You are passing too many parameters to the procedure. If you paste the procedure code we can help identify, however just do a count of the params and check to ensure you have all defined in the proc.
I don't see any code generating the SqlCommand object in your example.
If command is local to the class, there's a very good chance that it has already been used (which means it probably already has parameters added to it).
I also see no code that sets the command type to StoredProcedure. Depending on what the command text is, this could be the issue as well (if you're simply passing the stored procedure name without setting the type...it will see the command as having no parameters).
Re-Writing the code to use its own SqlConnection and SqlCommand would make this much easier to debug (unless, of course, it already is and you didn't give us that code).
EDIT
I just noticed that you're using the code inside a foreach loop without clearing the parameters. That is yet another issue (and probably the most likely cause for this issue). Just be sure to call command.Parameters.Clear() at the beginning of each loop before adding the new parameters.
Call the Clear method before adding the parameters.
It works the first time because your command object has no parameters. For each subsequent iteration you keep on adding another set of parameters to your command object.
You need to clear the parameters for your command object on each iteration.
How can I execute a stored procedure that takes in parameters without having to specify the prameters name? The name of the parameter in the stored procedure may change from CustomerID to CustID so I don't want to have to keep changing my code.
Rather than doing what is provided below where you specify the parameter name -
command.Parameters.Add("#dtStart", SqlDbType.DateTime);
command.Parameters["#dtStart"].Value = startDate;
command.Parameters.Add("#CustomerID", SqlDbType.NChar);
command.Parameters["#CustomerID"].Value = customerID;
I am looking to do something like this -
command.Parameters.Add(startDate, customerID);
The name of the parameter in the stored procedure may change from CustomerID to CustID
Slap the person who does that.
Parameter names are your reliable way of identifying a parameter. The other option is sequence, seems a lot more flaky.
I don't think you can create a SqlParameter object without specifying its name. However, you should be able to use the DeriveParameters method (see MSDN) to get a collection of parameters with the names automatically retreived from the SQL server.
You can find an example here. It looks roughly like this:
SqlCommand command = // create a command for calling the stored procedure
SqlCommandBuilder.DeriveParameters(command);
// Now you can set values of parameters in a loop
for(int i = 0; i < command.Parameters.Length; i++) {
var parameter = command.Parameters[i]
// Set value of ith parameter
}
You can create a nameless SQL parameter if you force its name to null or empty after it's been added to the Parameters collection, something like this:
var par = cmd.CreateParameter();
par.Value = myValue;
cmd.Parameters.Add(par); // this will change the name to "ParameterX"
par.ParameterName = null;
Use Parameter Discovery, scroll down on: http://msdn.microsoft.com/en-us/library/ff664692(PandP.50).aspx
Using Unnamed parameters is only possible with OdbcCommand and OleDbCommand object parameters.
You could use SQL's exec, which does not ask for parameter names:
command.CommandText = string.Format(
"exec dbo.YourProcedure {0}, '{1}'",
intParameter,
stringParameter.Replace("'","''")
);
command.ExecuteNonQuery();
If your parameter source is untrustworthy, be sure to escape single quotes in string parameters. It's done for stringParameter in the snippet above.
I've written a piece of c# code which executes a stored procedure on an MS SQL box. I Create the SP like so:
SqlCommand command = new SqlCommand(creditLimitRequestSP, connection);
command.CommandType = System.Data.CommandType.StoredProcedure;
I then create a set of parameters using the constructor for the parameters:
SqlParameter p1 = new SqlParameter(p1, p1Value);
vdnParam.Size = 7;
Some of my parameters are integers in which case I parse them like so:
int p4Value = 0;
bool parsedP4 = Int32.TryParse(p4AsAString, out p4Value);
SqlParameter p4;
if (parsedP4)
{
p4 = new SqlParameter("#p4", SqlDbType.Int, p4Value);
p4.Size = sizeof(Int32);
}
else
{
throw new InvalidFieldDataException("p4", p4AsString);
}
Then after I've parsed the parameters from a dictionary I add them like so:
command.Parameters.Add(p1);
command.Parameters.Add(p2);
command.Parameters.Add(p3);
command.Parameters.Add(p4);
command.Parameters.Add(p5);
command.Parameters.Add(p6);
When I execute the stored procedure I get an exception telling me is is expecting a parameter which I have added to the command. Why would it do this?
Initially I thought this might be because the parameters were being added in the wrong order but I changed them to match the order in the Stored procedure (event though it shouldn't matter as I'm using named parameters) and it didn't resolve anything.
The parameter in question does not have a default value in the SP, and it an integer value.
If the exception you get is telling that you are not adding a parameter, then it must be that you're not adding it. The parameters must match by name indeed (order doesn't matter), and all non-optional parameters must be present. Direction (Input, Output) must also be correctly set.
The exception message should tell you which parameter is not present, or has the wrong type.
There is no much to help you here, since there must be something at odd between what you believe you're passing and what you actually pass. You should monitor the RPC:Starting Event Class in the SQL Profiler and see exactly what are you passing.
I think I've found the answer...
p4 = new SqlParameter("#p4", SqlDbType.Int, p4Value);
The third Parameter is not the value it's the size of the param.
To set the value you need to call;
p4.Value = p4Value;
Going to test and will come back...
I have a stored procedure that returns two recordsets which i call using GetReader. I iterate the first, call IDataReader.NextResult(), then iterate the second.
I assign values to output parameters in the sp, but when i check the values after finishing with my reader, my output parameters are null. Looks like a bug. I don't want to use a select since i don't like fudges. Some snippets...
...
sp.Command.AddParameter("#SelectedTabID", selectedTabID, DbType.Int32);
sp.Command.AddParameter("#CurrentTabID", 0, DbType.Int32, ParameterDirection.Output);
sp.Command.AddParameter("#TypeID", 0, DbType.Int32, ParameterDirection.Output);
(note doing it this way or using AddOutputParameter() yields same results)
...
using(IDataReader reader = sp.GetReader())
{
while (reader.Read()) {...}
if (reader.NextResult()) {while (reader.Read()) {...}}
}
...
int one = (int)sp.OutputValues[0]; //null expected an int
int two = (int)sp.OutputValues[1]; //null expected an int
Looking forward to some gems of wisdom :)
You need to close the reader first and then retrieve the output parameter. Output params return null when the reader is open.
More info can be found here
http://amilagm.com/2010/11/output-variable-values-not-returned-from-sql-server-sp-in-c-sharp/
Hope this helps.
The easiest way to get the output parameter is to use an instantiated variable. What I mean is keep a reference to your parameters, then once you execute your sproc, then you can inspect them like this:
SqlCommand cmd = new SqlCommand();
cmd.Connection = ConfigurationManager.ConnectionStrings["MyCon"].ToString();
cmd.CommandText = "MySproc";
SqlParameter parmOut = new SqlParameter("#StuffIWant", SqlDbType.Int);
parmOut.Direction=ParameterDirection.Output;
cmd.Parameters.Add(parmOut);
cmd.ExecuteNonQuery();
string theThingIWant = parmOut.Value.ToString();
This may not be using a datareader, but you may be able to use this to find the right answer.
Good Luck.
Slightly confused here...are you expecting output of scalar values or some kind of recordset? Get Reader would only really make sense if you have e.g. some cursor coming back as out parameter...
You may want to call "ExecuteNonQuery()" on your command and ensure that you set the CommandType correctly (CommandType.StoredProcedure)
This is subsonic failing, works fine as a bog standard SQLConnection/Command
The answer is that you have to close the reader before you can access the output parameters.
From: This Page
Make sure you retrieve the recordset first as an SqlDataReader
via cmd.ExecuteReader() Process
through all recordsets and then...
Make sure you CLOSE the recordset,
or SqlDataReader via reader.Close()
before trying to retrieve the output parameters