Stored Procedure Default Value - c#

I'm a newbie when it comes to SQL. When creating a stored procedure with parameters as such:
#executed bit,
#failure bit,
#success bit,
#testID int,
#time float = 0,
#name varchar(200) = '',
#description varchar(200) = '',
#executionDateTime nvarchar(max) = '',
#message nvarchar(max) = ''
This is the correct form for default values in T-SQL? I have tried to use NULL instead of ''.
When I attempted to execute this procedure through C# I get an error referring to the fact that description is expected but not provided. When calling it like this:
cmd.Parameters["#description"].Value = result.Description;
result.Description is null. Should this not default to NULL (well '' in my case right now) in SQL?
Here's the calling command:
cmd.CommandText = "EXEC [dbo].insert_test_result #executed,
#failure, #success, #testID, #time, #name,
#description, #executionDateTime, #message;";
...
cmd.Parameters.Add("#description", SqlDbType.VarChar);
cmd.Parameters.Add("#executionDateTime", SqlDbType.VarChar);
cmd.Parameters.Add("#message", SqlDbType.VarChar);
cmd.Parameters["#name"].Value = result.Name;
cmd.Parameters["#description"].Value = result.Description;
...
try
{
connection.Open();
cmd.ExecuteNonQuery();
}
...
finally
{
connection.Close();
}

A better approach would be to change the CommandText to just the name of the SP, and the CommandType to StoredProcedure - then the parameters will work much more cleanly:
cmd.CommandText = "insert_test_result";
cmd.CommandType = CommandType.StoredProcedure;
This also allows simpler passing by name, rather than position.
In general, ADO.NET wants DBNull.Value, not null. I just use a handy method that loops over my args and replaces any nulls with DBNull.Value - as simple as (wrapped):
foreach (IDataParameter param in command.Parameters)
{
if (param.Value == null) param.Value = DBNull.Value;
}
However! Specifying a value with null is different to letting it assume the default value. If you want it to use the default, don't include the parameter in the command.

If you aren't using named parameters, MSSQL takes the parameters in the order received (by index). I think there's an option for this on the cmd object.
so your SQL should be more like
EXEC [dbo].insert_test_result
#executed = #executed,
#failure = #failure,
#success = #success,
#testID = #testID,
#time = #time,
#name = #name,
#description = #description,
#executionDateTime = #executionDateTime,
#message = #message;

cmd.CommandText = "insert_test_result";
cmd.Parameters.Add(new SQLParameter("#description", result.Description));
cmd.Parameters.Add(new SQLParameter("#message", result.Message));
try
{
connection.Open();
cmd.ExecuteNonQuery();
}
finally
{
connection.Close();
}

Related

How to return output varchar value from SQL stored procedure

I am trying to get a varchar value from SQL to use in function in C# here is how i tried to create Stored Procedure to return ,i appreciate any help.
#result
as an output value
CREATE PROCEDURE [dbo].[RolValidation]
#UserID int,
#result varchar(50) output
AS
BEGIN
Select #result=role from LogUser where UserID=#UserID
end
And here is the function in C#
if (sqlCon.State == ConnectionState.Closed)
sqlCon.Open();
SqlCommand sqlcmd = new SqlCommand("RolValidation", sqlCon);
sqlcmd.CommandType = CommandType.StoredProcedure;
sqlcmd.Parameters.AddWithValue("#UrunID", SqlDbType.Int);
sqlcmd.Parameters.Add("#result", SqlDbType.NVarChar,50).Direction = ParameterDirection.Output;
string rol = Convert.ToString(sqlcmd.Parameters["#UrunID"].Value);
sqlcmd.ExecuteNonQuery();
returnValue = rol;
It looks like that the code from your question is not the real code that you are working on so there might be other reasons why you don't get your value back.
However, judging from what I see if you modify the SP a little:
CREATE PROCEDURE [dbo].[RolValidation]
#UserID INT;
AS
BEGIN
SET NOCOUNT ON;
DECLARE #result varchar(50);
SET #result = Select role from LogUser where UserID=#UserID;
RETURN #result;
END
And in your C# code:
if (sqlCon.State == ConnectionState.Closed)
{
sqlCon.Open();
}
SqlCommand sqlcmd = new SqlCommand("RolValidation", sqlCon);
sqlcmd.CommandType = CommandType.StoredProcedure;
sqlcmd.Parameters.AddWithValue("#UserID", SqlDbType.Int);
sqlcmd.Parameters["#UserID"].Value = userID;
var rol = cmd.Parameters.Add("#result", SqlDbType.NVarChar, 50);
rol.Direction = ParameterDirection.ReturnValue
sqlcmd.ExecuteNonQuery();
returnValue = rol.Value;
Basically there were two main issues with your original code
1 - you should SET the value and then "RETURN" it. You can set it inline the SELECT query as you have done, but I kinda like this explicit approach a bit more
2 - you were trying to get the value before executing the query:
string rol = Convert.ToString(sqlcmd.Parameters["#UrunID"].Value);
sqlcmd.ExecuteNonQuery();
which is wrong, it should be the other way around - first execute the query then try to get the .Value
Other than that I'm not aware of the entire code but it's a good practice to wrap the connection and the command in using statements. If you don't have a good reason not to do that I suggest to change it.
P.S
Now I see that you are not passing the UserID value, at least in the code from the original question. So make sure to add this too, in my answer it's this row:
sqlcmd.Parameters["#UserID"].Value = userID;

Why i can not handle the store procedure return value is c#?

I'm new in c#,and want to write simple application work with sql server store procedure,in the sql server write this store procedure:
USE [mammutRecruitment]
ALTER PROCEDURE [dbo].[FirstStep]
#Name nvarchar(max),#Family nvarchar(max),#FatherName nvarchar(max),#BirthCertificate bigint,#PlaceOfBirth nvarchar(max),#BirthDate datetime,
#NationalCode bigint,#Religion nvarchar(max),#faith nvarchar(max),#Nationality nvarchar(max),#BloodGroup nvarchar(max)
AS
BEGIN
DECLARE #MYID bigint
insert into [dbo].[UserMainSpecifications] values(#Name,#Family,#FatherName,#BirthCertificate,#PlaceOfBirth,1,#BirthDate,#NationalCode,
#Religion,#faith,#Nationality,#BloodGroup,12,'123','123',1,2015-1-1,'12','123','1234',1)
select #MYID=[UserID] from [mammutRecruitment].[dbo].[UserMainSpecifications]
where [NationalCode]=#NationalCode
select #MYID as myID
END
and in c# write this code for call that:
using (SqlConnection con = new SqlConnection("Data Source=.;Initial Catalog=mammutRecruitment;Integrated Security=True"))
{
using (SqlCommand cmd = new SqlCommand("FirstStep", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#Name", SqlDbType.NVarChar).Value = m.Name;
cmd.Parameters.Add("#Family", SqlDbType.NVarChar).Value = m.Family;
cmd.Parameters.Add("#FatherName", SqlDbType.NVarChar).Value = m.FatherName;
cmd.Parameters.Add("#BirthCertificate", SqlDbType.BigInt).Value =Convert.ToInt64(m.BirthCertificate);
cmd.Parameters.Add("#PlaceOfBirth", SqlDbType.NVarChar).Value = m.PlaceOfBirth;
cmd.Parameters.Add("#BirthDate", SqlDbType.DateTime).Value =Convert.ToDateTime(dt.ToString());
cmd.Parameters.Add("#NationalCode", SqlDbType.BigInt).Value =Convert.ToInt64(m.NationalCode);
cmd.Parameters.Add("#Religion", SqlDbType.NVarChar).Value = m.Religion;
cmd.Parameters.Add("#faith", SqlDbType.NVarChar).Value = m.faith;
cmd.Parameters.Add("#Nationality", SqlDbType.NVarChar).Value = m.Nationality;
cmd.Parameters.Add("#BloodGroup", SqlDbType.NVarChar).Value = m.BloodGroup;
SqlParameter retval = cmd.Parameters.Add("#myID", SqlDbType.BigInt);
retval.Direction = ParameterDirection.ReturnValue;
con.Open();
cmd.ExecuteNonQuery();
var retunvalue = cmd.Parameters["#myID"].Value;
but in the this line i get zero value always:
var retunvalue = cmd.Parameters["#myID"].Value;
What happen?How can i solve that problem?thanks.
This line:
cmd.ExecuteNonQuery();
Is executing your query and not returning a value.
You could start by looking into using this instead:
cmd.ExecuteReader();
Or if you want the value of the first field of the first row, you could use this:
var returnValue = cmd.ExecuteScalar();
Which will give you an object that you can then convert or cast into the appropriate type for your method.
SqlCommand.ExecuteNonQuery Method ()
Executes a Transact-SQL statement against the connection and returns
the number of rows affected.
SqlCommand.ExecuteScalar Method ()
Executes the query, and returns the first column of the first row in
the result set returned by the query. Additional columns or rows are
ignored.
I believe you want the second method
You need to include #myID as an output parameter in your stored procedure definition:
ALTER PROCEDURE [dbo].[FirstStep]
#Name nvarchar(max),#Family nvarchar(max),#FatherName nvarchar(max),#BirthCertificate bigint,#PlaceOfBirth nvarchar(max),#BirthDate datetime,
#NationalCode bigint,#Religion nvarchar(max),#faith nvarchar(max),#Nationality nvarchar(max),#BloodGroup nvarchar(max)
, #myID bigint output
AS
And then remove the line
DECLARE #MYID bigint
You also need to add the parameter to cmd in your c# code:
cmd.Parameters.Add(retval);
you need define #MYID as output parameter.
USE [mammutRecruitment]
ALTER PROCEDURE [dbo].[FirstStep]
#MYID bigint output,#Name nvarchar(max),#Family nvarchar(max),#FatherName nvarchar(max),#BirthCertificate bigint,#PlaceOfBirth nvarchar(max),#BirthDate datetime,
#NationalCode bigint,#Religion nvarchar(max),#faith nvarchar(max),#Nationality nvarchar(max),#BloodGroup nvarchar(max)
AS
BEGIN
insert into [dbo].[UserMainSpecifications] values(#Name,#Family,#FatherName,#BirthCertificate,#PlaceOfBirth,1,#BirthDate,#NationalCode,
#Religion,#faith,#Nationality,#BloodGroup,12,'123','123',1,2015-1-1,'12','123','1234',1)
select #MYID = SCOPE_IDENTITY()
END
and add your command
SqlParameter pOut = new SqlParameter("#MYID", SqlDbType.BigInt);
pOut.Direction = ParameterDirection.Output;
cmd.Parameters.Add(pOut);
You can read the value now
cmd.ExecuteNonQuery();
long newId = (long)pOut.Value;
Actually, you need change that statement:
retval.Direction = ParameterDirection.ReturnValue;
to
retval.Direction = ParameterDirection.Output
because ExecuteNonQuery return:
Executes a Transact-SQL statement against the connection and returns the number of rows affected.
Although the ExecuteNonQuery returns no rows, any output parameters or return values mapped to parameters are populated with data.
End include your parameter to procedure definition:
#myID BIGINT OUTPUT
USE [mammutRecruitment]
ALTER PROCEDURE [dbo].[Firststep] #Name NVARCHAR(max),
#Family NVARCHAR(max),
#FatherName NVARCHAR(max),
#BirthCertificate BIGINT,
#PlaceOfBirth NVARCHAR(max),
#BirthDate DATETIME,
#NationalCode BIGINT,
#Religion NVARCHAR(max),
#faith NVARCHAR(max),
#Nationality NVARCHAR(max),
#BloodGroup NVARCHAR(max),
#myID BIGINT output
AS
BEGIN
INSERT INTO [dbo].[usermainspecifications]
VALUES (#Name,
#Family,
#FatherName,
#BirthCertificate,
#PlaceOfBirth,
1,
#BirthDate,
#NationalCode,
#Religion,
#faith,
#Nationality,
#BloodGroup,
12,
'123',
'123',
1,
2015 - 1 - 1,
'12',
'123',
'1234',
1)
SELECT #myID = [userid]
FROM [mammutRecruitment].[dbo].[usermainspecifications]
WHERE [nationalcode] = #NationalCode
END

Procedure or function expects parameter which was not supplied, when parameter is auto-generated

I'm trying to insert data in my db. this is the code im using
SqlCommand cmd = new SqlCommand("dbo.UsersInsert", cnn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#UserID", SqlDbType.Int);
cmd.Parameters.AddWithValue("#UserFirstName", FirstName.Text);
cmd.Parameters.AddWithValue("#UserMiddleName", MiddleName.Text);
cmd.Parameters.AddWithValue("#UserLastName", LastName.Text);
etc...
It is giving me error
Procedure or function 'UsersInsert' expects parameter '#UserID', which
was not supplied.
on cmd.ExecuteNonQuery(); line.
Here, My UserID is auto-generated in my Database. How do I resolve this?
Stored Procedure
#UserID INT OUTPUT,
#UserFirstName VARCHAR (50),
#UserMiddleName VARCHAR (50),
#UserLastName VARCHAR (50), etc...
AS
SET NOCOUNT ON
DECLARE #ReturnValue int
BEGIN
SELECT #ReturnValue = 0
INSERT [Users]
(
[UserFirstName]
,[UserMiddleName]
,[UserLastName] etc...
values (
#UserFirstName,
#UserMiddleName,
#UserLastName, etc.. )
IF (##Error <> 0) GOTO ERROR_HANDLER
GOTO OnExit
END
You should make it an ParameterDirection.Output
SqlParameter userIdParam = new SqlParameter("#UserID", SqlDbType.Int);
userIdParam.Direction = ParameterDirection.Output;
cmd.Parameters.Add(userIdParam);
This way you don't have to supply a value
The following code should work, change the sql to accept the parameters
SqlCommand cmd = new SqlCommand("dbo.UsersInsert #UserID out, #UserFirstName, #UserMiddleName, #UserLastName", cnn);
Then change the parameters as follows
var id = new SqlParameter("UserID", System.Data.SqlDbType.Int);
id.Direction = System.Data.ParameterDirection.Output;
cmd.Parameters.Add(id);
cmd.Parameters.AddWithValue("UserFirstName", FirstName.Text);
cmd.Parameters.AddWithValue("UserMiddleName", MiddleName.Text);
cmd.Parameters.AddWithValue("UserLastName", LastName.Text);

Error converting data type varchar to int

This is my stored procedure code
ALTER procedure [Proc_Add_User]
(#UserId varchar(20),
#UserName varchar(100),
#Page_Name varchar(20),
#AccessIndicator int,
#CreatedBy varchar(50),
#returnStatus varchar(50) output)
as
DECLARE #intErrorCode INT
DECLARE #Page_Indicator INT
begin
BEGIN TRAN
Set #Page_Indicator = (select Page_Indicator from Pages where Page_Name=#Page_Name);
if (select count(*) from Users where UserId=#UserId and UserName=#UserName) > 0 begin
if (select count(*) from User_Credentials where Page_Indicator=#Page_Indicator and
UserId=#UserId ) > 0
set #returnStatus='User already has access'
else
insert into User_Credentials(UserId,Page_Indicator,Access_Indicator,CreatedBy)
values (#UserId,#Page_Indicator,#AccessIndicator,#CreatedBy)
SELECT #intErrorCode = ##ERROR
IF (#intErrorCode <> 0) GOTO PROBLEM
end
else begin
insert into Users(UserId,UserName,CreatedBy)
values(#UserId,#UserName,#CreatedBy)
SELECT #intErrorCode = ##ERROR
IF (#intErrorCode <> 0) GOTO PROBLEM
insert into User_Credentials(UserId,Page_Indicator,Access_Indicator,CreatedBy)
values (#UserId,#Page_Indicator,#AccessIndicator,#CreatedBy)
SELECT #intErrorCode = ##ERROR
IF (#intErrorCode <> 0) GOTO PROBLEM
end
COMMIT TRAN
if(#returnStatus is null)
set #returnStatus='Success';
PROBLEM:
IF (#intErrorCode <> 0) BEGIN
set #returnStatus= 'Unexpected error occurred!'
ROLLBACK TRAN
end
end
And I am calling this from the code pasted below:
Con.Open();
cmd = new OleDbCommand();
cmd.Connection = Con;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "Proc_Add_User";
cmd.Parameters.Clear();
cmd.Parameters.Add("#UserId", SqlDbType.VarChar).Value = userLanId;
cmd.Parameters.Add("#UserName", SqlDbType.VarChar).Value = userName;
cmd.Parameters.Add("#Page_Name", SqlDbType.VarChar).Value = pageName;
cmd.Parameters.Add("#AccessIndicator", SqlDbType.Int).Value = accessIndicator;
cmd.Parameters.Add("#CreatedBy", SqlDbType.VarChar).Value = createdBy;
OleDbParameter output = new OleDbParameter("#returnStatus", SqlDbType.VarChar);
output.Direction = ParameterDirection.Output;
cmd.Parameters.Add(output);
int result = cmd.ExecuteNonQuery();
I am getting the error mentioned at the ExecuteNonQuery statement. What's confusing to me is I am able to execute the stored procedure in SSMS but not from my application (front-end). I provided the same values too yet it fails from my app.
I double checked to make sure the order of parameters passed match and are of same data type but still it throws this error. I can paste my stored proc code here if wanted so let me know..Thanks in advance!
EDIT
OOPS! I just realized that all the inserts are all happening and getting committed fine in the database. It's just this error is getting caught inside catch block in my app. Any ideas?
I can not ignore it because based on the return value of ExecuteNonQuery(), I have some statements and also it's not going through the code present after ExecuteNonQuery().
This is most likely because you are using SqlDbType with OleDbParameters:
OleDbParameter output = new OleDbParameter("#returnStatus", SqlDbType.VarChar);
This causes .NET to use the OleDbParameter(String, Object) constructor, setting the value of the parameter to SqlDbType.VarChar which it assumes is an int.
You should use this instead:
OleDbParameter output = new OleDbParameter("#returnStatus", OleDbType.VarChar);
And change your calls to cmd.Parameters.Add to use OleDbType as well.
Alternatively, you could use System.Data.SqlClient instead of OleDb

Stored procedure or function expects parameter which was not supplied

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 'Insertion' expects parameter '#Emp_no', which was not supplied*
My stored procedure is called Insertion. I have checked it thoroughly and no parameters is missing also I have checked it by using a label. The label shows the value but I don't know why I am getting the error.
My code is
try
{
SqlCommand cmd = new SqlCommand();
cmd.Parameters.Clear();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "Insertion";
cmd.Connection = con;
if (rdb_Male.Checked)
{
int #Emp_no = Convert.ToInt32(txtbx_Empno.Text);
string #Emp_name = txtbx_Emp_Name.Text;
double #phone = Convert.ToDouble(txtbx_Phone.Text);
string #Email = txtbx_Email.Text;
string #Password = txtbx_Pwd.Text;
string #Gender = rdb_Male.Text;
DateTime #Dob = Convert.ToDateTime(dob);
string #Address = txtbx_Address.Text;
string #Designation = txtbx_Designation.Text;
string #Qualification = txtbx_Qual.Text;
double #Experience = Convert.ToDouble(txtbx_Exp.Text);
double #Salary = Convert.ToDouble(txtbx_Sal.Text);
DateTime #Doj = Convert.ToDateTime(doj);
}
else if (rdb_Female.Checked)
{
int #Emp_no = Convert.ToInt32(txtbx_Empno.Text);
string #Emp_name = txtbx_Emp_Name.Text;
double #phone = Convert.ToDouble(txtbx_Phone.Text);
string #Email = txtbx_Email.Text;
string #Password = txtbx_Pwd.Text;
string #Gender = rdb_Female.Text;
DateTime #Dob = Convert.ToDateTime(dob);
string #Address = txtbx_Address.Text;
string #Designation = txtbx_Designation.Text;
string #Qualification = txtbx_Qual.Text;
double #Experience = Convert.ToDouble(txtbx_Exp.Text);
double #Salary = Convert.ToDouble(txtbx_Sal.Text);
DateTime #Doj = Convert.ToDateTime(doj);
}
if (con.State==ConnectionState.Closed)
con.Open();
LABEL.Text = txtbx_Empno.Text;
cmd.ExecuteNonQuery();
lbl_Errormsg.Visible = true;
lbl_Errormsg.Text = "Record Inserted Successfully";
con.Close();
}
and the stored procedure is
ALTER PROCEDURE dbo.Insertion
(
#Emp_no int,
#Emp_name varchar(30),
#phone numeric(10,0),
#Email varchar(30),
#Password varchar(10),
#Gender varchar(6),
#Dob date,
#Address varchar(100),
#Designation varchar(20),
#Qualification varchar(20),
#Experience numeric(4,2),
#Salary numeric(10,2),
#Doj date
)
AS
Begin
Insert into Register (Emp_no, Emp_name, phone, Email, Password, Gender, Dob, Address, Designation, Qualification, Experience, Salary, Doj)
Values(#Emp_no, #Emp_name, #phone, #Email, #Password, #Gender, #Dob, #Address, #Designation, #Qualification, #Experience, #Salary, #Doj)
End
Please help me. Thanks in advance.
Just a headsup, it might save someone a lot of time soul searching. If you have followed the recommendation here, like using AddWithValue in order to pass a paramter on, and you have everything verified and yet you are still getting the error message "Not supplied", check whether you have set the CommandType property of the command object to CommandType.StoredProcedure.
Not setting this property incurs the same message, believe me! Hope it helps someone.
You need to use SqlCommand.Parameters.AddWithValue:
cmd.Parameters.AddWithValue("#ParameterName", value);
or SqlCommand.Parameters.Add for other data types:
cmd.Parameters.Add("#ParameterName", SqlDbType.Int, 5);
cmd.Parameters["#ParameterName"].Value = value;
SqlCommand.Parameters.AddWithValue replaces the ambiguous overload of Add that took a string and object parameter. See MSDN for more info.
For others : I just faced the same error because one of my parameters was null. We need to check for it such as :
command.Parameters.AddWithValue("#phone", (object)phone?? DBNull.Value);
You need to use this:
cmd.Parameters.AddWithValue("#Emp_no", #Emp_no);
cmd.Parameters.AddWithValue("#Emp_name", #Emp_name);
cmd.Parameters.AddWithValue("#phone", #phone);
cmd.Parameters.AddWithValue("#Email", #Email);
cmd.Parameters.AddWithValue("#Password", #Password);
cmd.Parameters.AddWithValue("#Gender", #Gender);
cmd.Parameters.AddWithValue("#Dob", #Dob);
cmd.Parameters.AddWithValue("#Address", #Address);
cmd.Parameters.AddWithValue("#Designation", #Designation);
cmd.Parameters.AddWithValue("#Experience", #Experience);
cmd.Parameters.AddWithValue("#Salary", #Salary);
cmd.Parameters.AddWithValue("#Doj", #Doj);
Otherwise, it will throw that exception for each of the parameters.
Your Insertion stored procedure is expecting #Emp_no (along with about 15 other parameters). You cannot call the stored procedure without passing the parameters.
Take a look at this site for reference:
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlparametercollection.addwithvalue.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2
Everywhere you're defining variables, use Parameters.AddWithValue instead:
cmd.Parameters.AddWithValue("#Emp_no ", Convert.ToInt32(txtbx_Empno.Text));
This is how it can be done
using (var cmd = new SqlCommand("STORED_PROCEDURE_NAME", SqlConnection))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#PARAM_NAME", PARAM_VALUE);
}
Notice that AddWithValue, and CommandType.StoredProcedure both are essential.
"There's only one Add method that's obsoleted, the method that accepts a string for the parameter name and an object for the value. As you noted, you should call AddWithValue instead for this scenario."
http://social.msdn.microsoft.com/Forums/en-US/15bb16a4-0cf1-4289-b677-3b9d98f09298/parametersaddwithvalue-output-parameter-in-adonet-2?forum=adodotnetdataproviders
Not all Parameter.Add methods are depreciated. How are you suppose to make an OUTPUT parameter? You have to use Parameter.Add for this.
Same error message still these days scoping multiple problems - my issue was passing a null value to the parameter. The answer is to null check like so:
parameter.Value = (object)yourParamVal ?? DBNULL.Value;
Avoid parameters that have no value with the parameter set being DBNull.value

Categories