Retrieving SQL Server output variables in c# - c#

I have a stored procedure:
ALTER PROCEDURE [dbo].[pr_Tbl_Test_Insert]
#guidid uniqueidentifier output,
#sname nvarchar(50)
AS
-- INSERT a new row in the table.
INSERT [dbo].[Tbl_Test]
(
[id],
[name]
)
VALUES
(
ISNULl(#guidid, (newid())),
#sname
)
I need the id in C# and put it output in c#:
cmd.Parameters.AddWithValue("#guidid",_id);//_id is SqlGuid
cmd.Parameters.AddWithValue("#sname", "mehdi");
cmd.ExecuteNonQuery();
MessageBox.Show(_id.ToString());
but messagebox show the null value!!
How can I return the id?
I changed it to:
ALTER PROCEDURE [dbo].[pr_Tbl_Test_Insert]
#guidid uniqueidentifier output,
#sname nvarchar(50)
AS
DECLARE #NewID UNIQUEIDENTIFIER
SET #NewID = newid();
-- INSERT a new row in the table.
INSERT [dbo].[Tbl_Test]([id], [name]) VALUES(#NewID, #sname);
SET #guidid = #NewID
and C#
SqlParameter outparam = cmd.Parameters.Add("#guidid",SqlDbType.UniqueIdentifier);
outparam.Direction = ParameterDirection.Output;
cmd.Parameters.AddWithValue("#sname", "mehdi");
cmd.ExecuteNonQuery();
MessageBox.Show(_id.Value.ToString());
but it doesn't return anything

First of all - if it's an OUTPUT parameter, you cannot use .AddWithValue in C# - you need to use:
SqlParameter outParam = cmd.Parameters.Add("#guidid", SqlDbType.Uniqueidentifier);
outParam.Direction = ParameterDirection.Output;
and also, in your T-SQL code, you need to assign the new value to the output parameter!
ALTER PROCEDURE [dbo].[pr_Tbl_Test_Insert]
#guidid uniqueidentifier output,
#sname nvarchar(50)
AS
DECLARE #NewID UNIQUEIDENTIFIER
SET #NewID = newid();
-- INSERT a new row in the table.
INSERT [dbo].[Tbl_Test]([id], [name]) VALUES(#NewID, #sname);
SET #guidid = #NewID
Update: if you run this in your SQL Server Mgmt Studio - does it show anything??
DECLARE #insertedID UNIQUEIDENTIFIER
EXEC dbo.pr_Tbl_Test_Insert #guidid = #insertedID OUTPUT,
#sname = N'TestUser' -- nvarchar(50)
SELECT #insertedID
and in your C# - you have to read out the value of the output parameter after calling ExecuteNonQuery!
SqlParameter outparam = cmd.Parameters.Add("#guidid",SqlDbType.UniqueIdentifier);
outparam.Direction = ParameterDirection.Output;
cmd.Parameters.AddWithValue("#sname", "mehdi");
cmd.ExecuteNonQuery();
Guid newlyInsertedID = new Guid(cmd.Parameters["#guidid"].Value);
MessageBox.Show(newlyInsertedID.ToString());

Before you execute the query you need to specify the direction of the parameter, in this case output. e.g.:
cmd.Parameters.AddWithValue("#guidid",_id);//_id is SqlGuid
cmd.Parameters.AddWithValue("#sname", "mehdi");
cmd.Parameters["#guidid"].Direction = ParameterDirection.Output
cmd.ExecuteNonQuery();
MessageBox.Show(cmd.Parameters["#guidid"].Value.ToString());

You need to construct a SqlParameter using one of the constructors that lets you specify a ParameterDirection, such as this one. Alternatively, construct your parameter and then set the direction using the Direction property.
Check this link on MSDN for more information.

Why are you setting the #guidid uniqueidentifier output as an output parameter? It means it will override it once you execute the stored procedure. If that's your intention, then you need to add a statement after the insert statement to set the output parameter to the value you want. something like this: select #guidid = #generatedID. Yeah look at marc_s code, that's the way you are supposed to do it.

I also found this very frustrating and I could not understand the issue. Although many answers are correct, there was one simple line that was often overlooked by me and others, namely the command needs to be store procedure not just any sql with parameters, so I hope this helps:
cmd.CommandType = CommandType.StoredProcedure;
cmd.Txt should look like this:
#"my_stored_proct "
NOT
#"my_stored_proct #p1, #p2, #p3 out"
So putting it all together. You might want to separate it into several methods. and add TimeOuts etc. However these are what I think are the critical parts that differ from other commands witout output Parameters.
using (SqlCommand cmd= new SqlCommand())
{
cmd.Text= ...;
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter outParam = cmd.Parameters.Add("#guidid", SqlDbType.Uniqueidentifier);
outParam.Direction = ParameterDirection.Output;
using (var connection = new SqlConnection(this.myConnectionString))
{
connection.Open();
cmd.Connection = connection;
try
{
cmd.ExecuteNonQuery();
}
catch
{
// put your sql catches etc. here..
throw;
}
}
var outValue = outParam.Value;
//query outValue e.g. ToString()
}

Related

Procedure or function 'SP_CheckEmployeeCode' expects parameter '#result', which was not supplied [duplicate]

I am trying to insert data into a SQL Server database by calling a stored procedure, but I am getting the error
Procedure or function 'SHOWuser' expects parameter '#userID', which was not supplied.
My stored procedure is called SHOWuser. I have checked it thoroughly and no parameters is missing.
My code is:
public void SHOWuser(string userName, string password, string emailAddress, List<int> preferences)
{
SqlConnection dbcon = new SqlConnection(conn);
try
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = dbcon;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "SHOWuser";
cmd.Parameters.AddWithValue("#userName", userName);
cmd.Parameters.AddWithValue("#password", password);
cmd.Parameters.AddWithValue("#emailAddress", emailAddress);
dbcon.Open();
int i = Convert.ToInt32(cmd.ExecuteScalar());
cmd.Parameters.Clear();
cmd.CommandText = "tbl_pref";
foreach (int preference in preferences)
{
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("#userID", Convert.ToInt32(i));
cmd.Parameters.AddWithValue("#preferenceID", Convert.ToInt32(preference));
cmd.ExecuteNonQuery();
}
}
catch (Exception)
{
throw;
}
finally
{
dbcon.Close();
}
and the stored procedure is:
ALTER PROCEDURE [dbo].[SHOWuser]
(
#userName varchar(50),
#password nvarchar(50),
#emailAddress nvarchar(50)
)
AS
BEGIN
INSERT INTO tbl_user(userName, password, emailAddress)
VALUES (#userName, #password, #emailAddress)
SELECT
tbl_user.userID, tbl_user.userName,
tbl_user.password, tbl_user.emailAddress,
STUFF((SELECT ',' + preferenceName
FROM tbl_pref_master
INNER JOIN tbl_preferences ON tbl_pref_master.preferenceID = tbl_preferences.preferenceID
WHERE tbl_preferences.userID = tbl_user.userID
FOR XML PATH ('')), 1, 1, ' ' ) AS Preferences
FROM
tbl_user
SELECT SCOPE_IDENTITY();
END
This is the second stored procedure tbl_pref which is used in the same function:
ALTER PROCEDURE [dbo].[tbl_pref]
#userID int,
#preferenceID int
AS
BEGIN
INSERT INTO tbl_preferences(userID, preferenceID)
VALUES (#userID, #preferenceID)
END
In my case I received this exception even when all parameter values were correctly supplied but the type of command was not specified :
cmd.CommandType = System.Data.CommandType.StoredProcedure;
This is obviously not the case in the question above, but exception description is not very clear in this case, so I decided to specify that.
I came across this issue yesterday, but none of the solutions here worked exactly, however they did point me in the right direction.
Our application is a workflow tool written in C# and, overly simplified, has several stored procedures on the database, as well as a table of metadata about each parameter used by each stored procedure (name, order, data type, size, etc), allowing us to create as many new stored procedures as we need without having to change the C#.
Analysis of the problem showed that our code was setting all the correct parameters on the SqlCommand object, however once it was executed, it threw the same error as the OP got.
Further analysis revealed that some parameters had a value of null. I therefore must draw the conclusion that SqlCommand objects ignore any SqlParameter object in their .Parameters collection with a value of null.
There are two solutions to this problem that I found.
In our stored procedures, give a default value to each parameter, so from #Parameter int to #Parameter int = NULL (or some other default value as required).
In our code that generates the individual SqlParameter objects, assigning DBNull.Value instead of null where the intended value is a SQL NULL does the trick.
The original coder has moved on and the code was originally written with Solution 1 in mind, and having weighed up the benefits of both, I think I'll stick with Solution 1. It's much easier to specify a default value for a specific stored procedure when writing it, rather than it always being NULL as defined in the code.
Hope that helps someone.
Your stored procedure expects 5 parameters as input
#userID int,
#userName varchar(50),
#password nvarchar(50),
#emailAddress nvarchar(50),
#preferenceName varchar(20)
So you should add all 5 parameters to this SP call:
cmd.CommandText = "SHOWuser";
cmd.Parameters.AddWithValue("#userID",userID);
cmd.Parameters.AddWithValue("#userName", userName);
cmd.Parameters.AddWithValue("#password", password);
cmd.Parameters.AddWithValue("#emailAddress", emailAddress);
cmd.Parameters.AddWithValue("#preferenceName", preferences);
dbcon.Open();
PS: It's not clear what these parameter are for. You don't use these parameters in your SP body so your SP should looks like:
ALTER PROCEDURE [dbo].[SHOWuser] AS BEGIN ..... END
In my case I got the error on output parameter even though I was setting it correctly on C# side I figured out I forgot to give a default value to output parameter on the stored procedure
ALTER PROCEDURE [dbo].[test]
(
#UserID int,
#ReturnValue int = 0 output --Previously I had #ReturnValue int output
)
In my case, It was returning one output parameter and was not Returning any value.
So changed it to
param.Direction = ParameterDirection.Output;
command.ExecuteScalar();
and then it was throwing size error. so had to set the size as well
SqlParameter param = new SqlParameter("#Name",SqlDbType.NVarChar);
param.Size = 10;
After researching, I realized that I did not specify
command.CommandType = System.Data.CommandType.StoredProcedure;
After adding this, my application ran properly.
in my case, I was passing all the parameters but one of the parameter my code was passing a null value for string.
Eg: cmd.Parameters.AddWithValue("#userName", userName);
in the above case, if the data type of userName is string, I was passing userName as null.

Error - stored procedure has no parameters and arguments were supplied in c#

When I'm trying to call store procedure and return the value from the procedure, I'm getting the error message - procedure has no parameters and arguments were supplied
Below is the c# code:
using (SqlCommand command2 = new SqlCommand("getservername8", conn1))
{
command2.CommandType = CommandType.StoredProcedure;
command2.Parameters.Add("#s", SqlDbType.NVarChar, 500);
command2.Parameters["#s"].Direction = ParameterDirection.Output;
command2.ExecuteNonQuery();
string server = (string)command2.Parameters["#s"].Value;
}
Below is the stored procedure:
GO
ALTER procedure [dbo].[getservername9]
#s varchar(50)
as begin
declare #server_name varchar(500)
select #server_name = short_description from [Event_alerts].[dbo].[event_alerts]
select #s= SUBSTRING(#server_name, CHARINDEX('-', #server_name) + 15, 50)
return #s
end
Stored procedure gets executed with no error.Any help will be much appreciated
Use ExecuteScalar instead of Executenonquery. Please refer..
https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.executescalar?view=dotnet-plat-ext-3.1
Please make below changes to your code -
Mark your variable in the stored procedure as output like below -
#s varchar(50) output
You cannot return varchar output values like you added in stored procedure.
Stored procedures always return integer values when you use return
statement here. In your case you will get below error when executed -
(the same can be observed in .NET end as well).
declare #s varchar(50)
exec [dbo].[getservername9] #s
Conversion failed when converting the varchar value '' to data
type int.
Remove the return statement from stored procedure which will automatically return the value back to .NET code.
Finally make the stored procedure names consistent in both .NET and SQL procedure.
First is to change your store procedure name, in the code you are using getservername8 while your stored procedure name is getservername9, the second point you need to mark your parameter as output as show in the code below
Code :
using (SqlCommand command2 = new SqlCommand("getservername", conn1))
{
command2.CommandType = CommandType.StoredProcedure;
command2.Parameters.Add("#s", SqlDbType.NVarChar, 500);
command2.Parameters["#s"].Direction = ParameterDirection.Output;
command2.ExecuteNonQuery();
string server = (string)command2.Parameters["#s"].Value;
}
Stored Procedure :
GO
ALTER procedure [dbo].[getservername]
#s varchar(50) output
as begin
declare #server_name varchar(500)
select #server_name = short_description from [Event_alerts].[dbo].[event_alerts]
select #s= SUBSTRING(#server_name, CHARINDEX('-', #server_name) + 15, 50)
return #s
end

Inserting with an Auto-Incrementing ID

I am inserting into a database using a stored procedure and i am getting the error:
Procedure or function 'sp_Addrecord' expects parameter '#RecordNumber', which was not supplied.
RecordNumber is an auto incrementing ID so i understand id have to omit it from my insert command and specify which columns and where i have to insert to avoid this but i am calling the procedure which is handled by another class so where would i be able to specify this as you would normally say something like this:
SqlCommand cmd = new SqlCommand("INSERT INTO CARS (carDate, carTime) Values (#Date, #Time)", conDatabase);
Here is my code, i avoided the using statement for simplicity of this example:
List<CarRecord> carRecords;
private void Save_Record_Click(object sender, RoutedEventArgs e)
{
SqlConnection conDatabase = new SqlConnection(String.Format(#"Data Source={0};Initial Catalog={1};Persist Security Info=True;User ID={2};Password={3}", SQLFunctions.connectSQL.SQLSERVER_ID, SQLFunctions.connectSQL.SQLDatabaseName, SQLFunctions.connectSQL.SQLServerLoginName, SQLFunctions.connectSQL.SQLServerPassword));
conDatabase.Open();
SqlCommand cmd = new SqlCommand("sp_Addrecord", conDatabase);
cmd.CommandType = CommandType.StoredProcedure;
cmd.ExecuteNonQuery();
conDatabase.Close();
}
public bool Addrecord(CarRecord DataRecord)
{
return ExecuteNonQuery("sp_Addrecord", null,
CreateParameter("#Date", SqlDbType.NVarChar, DataRecord.carDate),
CreateParameter("#Time", SqlDbType.NVarChar, DataRecord.carTime),
);
}
EDIT - Stored Procedure:
USE [SDC Logging]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_Addrecord]
#RecordNumber int,
#Date nvarchar(50),
#Time nvarchar(50),
AS
BEGIN
SET NOCOUNT ON;
WITH [source](RecordNumber, Date, Time)
AS
(
SELECT #RecordNumber, #Date, #Time,
)
MERGE dbo.Bags AS [target] USING [source]
ON [target].Date = [source].Date
WHEN MATCHED THEN UPDATE SET
[target].Date = #Date,
[target].Time = #Time,
WHEN NOT MATCHED THEN
INSERT ( Date, Time, )
VALUES( #Date, #Time, );
SELECT SCOPE_IDENTITY()
END
The error says it all. Your sp_Addrecord has a parameter specified that you are supplying. Basically, the parameters you specify here...
return ExecuteNonQuery("sp_Addrecord", null,
CreateParameter("#Date", SqlDbType.NVarChar, DataRecord.carDate),
CreateParameter("#Time", SqlDbType.NVarChar, DataRecord.carTime),
);
must match the name and datatype of the parameters defined by sp_Addrecord stored procedure. In addition, make sure your stored procedure's query matches this query...
INSERT INTO CARS (carDate, carTime) Values (#Date, #Time)
Edit based on your Edit
You need to specified the #RecordNumber parameter here...
return ExecuteNonQuery("sp_Addrecord", null,
CreateParameter("#RecordNumber", SqlDbType.Int, DataRecord.recordNumber),
CreateParameter("#Date", SqlDbType.NVarChar, DataRecord.carDate),
CreateParameter("#Time", SqlDbType.NVarChar, DataRecord.carTime),
);
Don't worry about the insert just make sure that when inserting you pass a "invalid record number" such as -1, if the MERGE statement doesn't find the record with id of -1 it will successfully insert the record with an auto-generated Id with the help of your identity column
Try This.
You don't need to call separate method Addrecord.
However, you still want to use a separate method. Add code below in the AddRecord method and remove existing code:
SqlParameter []parms = new SqlParameter[1];
parms[0] = new SqlParameter("#Date",DataRecord.carDate) ;
parms[1] = new SqlParameter("#Time",DataRecord.carTime) ;
cmd.Parameters.AddRange(parms);
cmd.CommandType = CommandType.StoredProcedure;
cmd.ExecuteNonQuery();
conDatabase.Close();

SQL SERVER 2005 return value

Hi all I have the following stored procedure
#UserName varchar(150),
#UserEmail varchar(300),
#UserPassword varchar(150),
#ContactNumber varchar(150),
#ContactMobile varchar(150),
#AreaOfCountry varchar(150),
#UserId int OUTPUT,
#AllreadyReg int OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
--DECLARE #UserId int, #AllreadyReg int
IF (SELECT COUNT(UserId) FROM Users WHERE (UserName = #UserName) OR (UserEmail = #UserEmail)) > 0
BEGIN
SET #UserId = 0
SET #AllreadyReg = 1
END
ELSE
BEGIN
INSERT INTO Users (UserName,UserEmail,UserPassword,ContactNumber,ContactMobile,AreaOfCountry) VALUES (#UserName,#UserEmail,#UserPassword,#ContactNumber,#ContactMobile,#AreaOfCountry)
SELECT #UserId = SCOPE_IDENTITY()
SET #AllreadyReg = 0
END
however when I use it using c# and asp.net its not returning anything, however when I just execute it it does have a results #UserId and #AllreadyReg but the return value is 0 and a single field.
my c# code is below but it never has any rows
using (SqlConnection con = new SqlConnection(connectionString))
{
Response.Write("Line 61");
using (SqlCommand cmd = new SqlCommand("spR_Register", con))
{
Response.Write("line 64");
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#UserName", TxtUsername.Text.Trim());
cmd.Parameters.AddWithValue("#UserEmail", TxtEmail.Text.Trim());
cmd.Parameters.AddWithValue("#UserPassword", TxtPassword.Text.Trim());
cmd.Parameters.AddWithValue("#ContactNumber", TxtPhone.Text);
cmd.Parameters.AddWithValue("#ContactMobile", TxtMobile.Text);
cmd.Parameters.AddWithValue("#AreaOfCountry", TxtAreaOfCountry.SelectedValue);
cmd.Parameters.AddWithValue("#UserId", ParameterDirection.Output);
cmd.Parameters.AddWithValue("#AllreadyReg", ParameterDirection.Output);
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
if (reader.HasRows)
{
Response.Write("line 78");
etc etc
can anyone help
thanks
With the edit: the mistake is using ExecuteReader on a command that doesn't select a data grid - that should be done with ExecuteNonQuery.
The important thing here is how the parameter is added. For example:
var alreadyReg = cmd.CreateParameter();
alreadyReg.Direction = System.Data.ParameterDirection.Output;
alreadyReg.ParameterName = "AllreadyReg";
alreadyReg.DbType = DbType.Int32;
cmd.Parameters.Add(alreadyReg);
//...
cmd.ExecuteNonQuery();
//...
int val = (int)alreadyReg.Value;
Depending on the type of DbCommand object, there may be an overload that accepts all of these in one line - the above assumes just DbCommand. With SqlCommand, you can simplify a bit:
var alreadyReg = cmd.Parameters.Add("AllreadyReg", SqlDbType.Int);
alreadyReg.Direction = ParameterDirection.Output;
//...
cmd.ExecuteNonQuery();
//...
int val = (int)alreadyReg.Value
You might have already handled it, but just in case, make sure to specify direction of parameter in c# code.
Here
cmd.Parameters.AddWithValue("#UserId", ParameterDirection.Output);
wrong usage of AddWithValue. The second parameter is parsed as parameter value, not direction type. Use proper parameter contructor and the add the result to collection.

OdbcCommand on Stored Procedure - "Parameter not supplied" error on Output parameter

I'm trying to execute a stored procedure (against SQL Server 2005 through the ODBC driver) and I recieve the following error:
Procedure or Function 'GetNodeID' expects parameter '#ID', which was not supplied.
#ID is the OUTPUT parameter for my procedure, there is an input #machine which is specified and is set to null in the stored procedure:
ALTER PROCEDURE [dbo].[GetNodeID]
#machine nvarchar(32) = null,
#ID int OUTPUT
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS(SELECT * FROM Nodes WHERE NodeName=#machine)
BEGIN
SELECT #ID = (SELECT NodeID FROM Nodes WHERE NodeName=#machine)
END
ELSE
BEGIN
INSERT INTO Nodes (NodeName) VALUES (#machine)
SELECT #ID = (SELECT NodeID FROM Nodes WHERE NodeName=#machine)
END
END
The following is the code I'm using to set the parameters and call the procedure:
OdbcCommand Cmd = new OdbcCommand("GetNodeID", _Connection);
Cmd.CommandType = CommandType.StoredProcedure;
Cmd.Parameters.Add("#machine", OdbcType.NVarChar);
Cmd.Parameters["#machine"].Value = Environment.MachineName.ToLower();
Cmd.Parameters.Add("#ID", OdbcType.Int);
Cmd.Parameters["#ID"].Direction = ParameterDirection.Output;
Cmd.ExecuteNonQuery();
_NodeID = (int)Cmd.Parameters["#Count"].Value;
I've also tried using Cmd.ExecuteScalar with no success. If I break before I execute the command, I can see that #machine has a value.
If I execute the procedure directly from Management Studio, it works correctly.
Any thoughts? Thanks
Try replacing :
OdbcCommand Cmd = new OdbcCommand("GetNodeID", _Connection);
Cmd.CommandType = CommandType.StoredProcedure;
With :
OdbcCommand Cmd = new OdbcCommand("{call GetNodeID(?,?)}", _Connection);
More info :
http://support.microsoft.com/kb/310130
I'm not exactly sure what you mean by
there is an input #machine which is
specified and is set to null in the
stored procedure
In your proc's signature, this line:
#machine nvarchar(32) = null
doesn't mean that you're setting #machine to null inside the proc - it means you're assigning a default value to be used in case the parameter is missing (in this case, null is the value to be used for a missing param).
Getting the error about #ID being missing would happen if you were calling this stored procedure without passing any parameters at all (#machine would not be flagged as a problem since it has a default value defined). Your code example looks fine to me - are you sure the stored proc isn't being called from somewhere else in your program (somewhere where no parameters are being added)?
Stored procedure with input parameters and ODBC Connection:
create a stored procedure:
create procedure proc_name #parm1 varchar(20), #parm2 varchar(10) as begin insert into table_name values(#parm1,#parm2);end
This code works in SQL Server.
private void button1_Click(object sender, EventArgs e)
{
string name = txtname.Text;
string num = txtnum.Text;
OdbcConnection con = new OdbcConnection("dsn=naveenk_m5");
OdbcCommand cmd = new OdbcCommand("{call proc1(?,?)}",con);
cmd.Parameters.Add("#parm1", OdbcType.VarChar).Value=name;
cmd.Parameters.Add("#parm2", OdbcType.VarChar).Value = num;
con.Open();
cmd.ExecuteNonQuery();
con.Close();
MessageBox.Show("inserted a row");
}

Categories

Resources