SQL Output Parameter - c#

I have a questionnaire which stores answers for each user who does the test. I need to store the output in the database (which is the user doing the test.) I'm not quite sure what i am doing wrong. Currently my inputID returns 0. (InputAnswers inputs the test answers for that user to database)
CREATE PROCEDURE [dbo].[InputAnswers]
#QuestionID int,
#InputID int OUTPUT,
#Answer nchar,
#Remark nvarchar(50)
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO Answers (InputID, QuestionID, Answer, Remark) VALUES (#InputID, #QuestionID, #Answer, #Remark)
END
The code below loads the answers from the list view which holds the questions:
private void LoadAnswers(int inputID)
{
foreach (StepControl step in dckSteps.Children)
{
foreach (QuestionControl quest in step.listQuestions.Items)
{
int questionID = quest.questionID;
string answer = quest.answer;
string remark = quest.txtRemark.Text;
SqlConnection conDatabase = new SqlConnection(String.Format(#"Data Source={0};Initial Catalog={1};Persist Security Info=True;User ID={2};Password={3}", SQLSERVER_ID, SQLDatabaseName, SQLServerLoginName, SQLServerPassword));
string query = "InputAnswers";
SqlCommand cmd = new SqlCommand(query, conDatabase);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#InputID", SqlDbType.Int).Value = inputID;
cmd.Parameters.Add("#QuestionID", SqlDbType.Int).Value = questionID;
cmd.Parameters.Add("#Answer", SqlDbType.NChar).Value = answer;
cmd.Parameters.Add("#Remark", SqlDbType.NVarChar).Value = remark;
conDatabase.Open();
cmd.ExecuteNonQuery();
conDatabase.Close();
}
}
}
I then load these answers into the button click method:
private void btnSubmit_Click(object sender, RoutedEventArgs e)
{
string name = txtName.Text;
string cno = txtCNO.Text;
var date = datePicker.SelectedDate;
int inputID = 0;
SqlConnection conDatabase = new SqlConnection(String.Format(#"Data Source={0};Initial Catalog={1};Persist Security Info=True;User ID={2};Password={3}", SQLSERVER_ID, SQLDatabaseName, SQLServerLoginName, SQLServerPassword));
string query = "SaveInput";
SqlCommand cmd = new SqlCommand(query, conDatabase);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#InputID", SqlDbType.Int).Value = ParameterDirection.Output;
cmd.Parameters.Add("#Name", SqlDbType.NVarChar).Value = name;
cmd.Parameters.Add("#CNO", SqlDbType.NVarChar).Value = cno;
cmd.Parameters.Add("#Date", SqlDbType.DateTime).Value = date;
conDatabase.Open();
cmd.ExecuteNonQuery();
conDatabase.Close();
LoadAnswers(inputID);
}
This all works correctly apart from sending the OUTPUT back to the database. Any ideas?
EDIT: The procedure SaveInput looks like this: (SaveInput stores the user info)
CREATE PROCEDURE [dbo].[SaveInput]
#InputID int OUTPUT,
#Name nvarchar(50),
#CNO nvarchar(50),
#Date DATETIME
AS
BEGIN
SET NOCOUNT ON;
IF(#InputID = 0)
BEGIN
INSERT INTO Input (Name, CNO, Date) VALUES (#Name, #CNO, #Date)
SET #InputID = ##IDENTITY
END
ELSE
BEGIN
UPDATE Input SET Name = #Name,
CNO = #CNO,
Date = #Date
WHERE InputID = #InputID
END
END
I have a feeling i don't need to use OUTPUT on both procedures.

This is at least part of the problem:
cmd.Parameters.Add("#InputID", SqlDbType.Int).Value = ParameterDirection.Output;
That's creating an input parameter - but giving it a value which is the enum value ParameterDirection.Output. You want:
cmd.Parameters.Add("#InputID", SqlDbType.Int).Direction = ParameterDirection.Output;
You then need to fetch the result from the parameter after executing the command:
cmd.ExecuteNonQuery();
// You might want to store the parameter reference in a local variable instead
// of fetching it again afterwards.
int inputId = (int) cmd.Parameters["#InputID"].Value;
If you want the parameter to be input/output though, you should be using ParameterDirection.InputOutput (and giving it a value before executing the command). For example:
int inputId = ...;
var inputIdParameter = cmd.Parameters.Add("#InputID", SqlDbType.Int);
inputIdParameter.Direction = ParameterDirection.InputOutput;
inputIdParameter.Value = inputId;
...
cmd.ExecuteNonQuery();
inputId = (int) inputIdParameter.Value;

Related

Convert Command.ExecuteScalar() To Int

I need to insert a line in my question table and retrieve the inserted id. I initialize my sql command and execute it with ExecuteScalar(). I'm trying to convert the result of this method to int but I can not do it.
I tried to do that:
int result = Convert.ToInt32(Command.ExecuteScalar));
or
int result = (int)Command.ExecuteScalar();
but nothing work
here is my function
public int AddQuestionOrientation(Question questionForAdd)
{
try
{
con = new SqlConnection(connectionString);
con.Open();
SqlCommand command;
String sql = "";
sql = "INSERT INTO QUESTION VALUES(#Libelle,
#Bareme,2,#Filliere)";
SqlParameter param = new SqlParameter();
param.ParameterName = "#Libelle";
param.Value = questionForAdd.Libelle;
SqlParameter param2 = new SqlParameter();
param2.ParameterName = "#Bareme";
param2.Value = questionForAdd.Bareme;
SqlParameter param3 = new SqlParameter();
param3.ParameterName = "#Filliere";
param3.Value = questionForAdd.IdFiliere;
command = new SqlCommand(sql, con);
command.Parameters.Add(param);
command.Parameters.Add(param2);
command.Parameters.Add(param3);
int idQuestionInserted = (int)command.ExecuteScalar();
command.Dispose();
con.Close();
return idQuestionInserted;
}
catch(Exception ex)
{
return 0;
}
}
If I try with the cast (int), I have the message error:
Object reference not set to an instance of an object
If I try with the Convert.ToInt32, my variable "IdQuestionInserted" is equal to 0.
This is a big departure from where you started. But you have several issue going on there. You should use the USING statement around objects with the IDisposable interface (connections, commands, etc...).
This code is all untested but should be really close.
Start with creating a stored procedure so you can start creating layers in your application.
create Procedure Question_Insert
(
#Libelle varchar(50)
, #Bareme varchar(50)
, #Filliere varchar(50)
, #QuestionID int output
) as
set nocount on;
INSERT INTO QUESTION
(
Libelle
, Bareme
, Filliere
)
values
(
#Libelle
, #Bareme
, #Filliere
)
select #QuestionID = SCOPE_IDENTITY()
Then in your dotnet code you need to change up a few things to make it cleaner and more robust. Ideally you should do something better than simply return 0 when there is an error. It will be really tough to debug when something goes wrong if you simply return a 0. This is like an error message that says, "An error occurred". Pretty useless. Do something with the error. Capture the message to enable you to fix it.
public int AddQuestionOrientation(Question questionForAdd)
{
try
{
using (SqlConnection con = new SqlConnection(connectionString))
{
con.Open();
using (SqlCommand command = new SqlCommand("Question_Insert"))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#Libelle", SqlDbType.VarChar, 50).Value = questionForAdd.Libelle;
command.Parameters.Add("#Bareme", SqlDbType.VarChar, 50).Value = questionForAdd.Bareme;
command.Parameters.Add("#Filliere", SqlDbType.VarChar, 50).Value = questionForAdd.IdFiliere;
command.Parameters.Add("#QuestionID", SqlDbType.Int).Direction = ParameterDirection.Output;
command.ExecuteNonQuery();
return int.Parse(command.Parameters["#QuestionID"].Value.ToString());
}
}
}
catch (Exception ex)
{
return 0;
}
}
To get inserted id use SCOPE_IDENTITY() add SELECT CAST(scope_identity() AS int to command query to do
INSERT INTO QUESTION
VALUES(#Libelle, #Bareme, 2, #Filliere);
SELECT CAST(scope_identity() AS int;
this query will return inserted id for you.

How can I solve this error "Does not allow NULL, Insert Aborted"?

I'm trying to call a stored procedure to make an insert:
private void button1_Click(object sender, EventArgs e)
{
string connectionString = #"Data Source=******;Initial Catalog=**********;Integrated Security=True";
using (SqlConnection sqlCon = new SqlConnection(connectionString: connectionString))
{
using (SqlCommand cmd = new SqlCommand("InsertAngajat", sqlCon))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#Nume", SqlDbType.VarChar).Value = textBox1.Text;
cmd.Parameters.Add("#Prenume", SqlDbType.VarChar).Value = textBox2.Text;
cmd.Parameters.Add("#DataNasterii", SqlDbType.Date).Value = textBox4.Text;
cmd.Parameters.Add("#DataAngajare", SqlDbType.Date).Value = DateTime.Today.ToString();
cmd.Parameters.Add("#cnp", SqlDbType.Char).Value = textBox3.Text.ToCharArray();
cmd.Parameters.Add("#Localitate", SqlDbType.VarChar).Value = textBox8.Text;
cmd.Parameters.Add("#Judet", SqlDbType.VarChar).Value = textBox10.Text;
cmd.Parameters.Add("#Strada", SqlDbType.VarChar).Value = textBox9.Text;
cmd.Parameters.Add("#Departament", SqlDbType.VarChar).Value = comboBox1.Text;
cmd.Parameters.Add("#Telefon", SqlDbType.Char).Value = textBox5.Text.ToCharArray();
if (checkBox1.Checked)
cmd.Parameters.Add("#Sex", SqlDbType.Char).Value = 'M';
else if (checkBox2.Checked)
cmd.Parameters.Add("#Sex", SqlDbType.Char).Value = 'F';
else
MessageBox.Show("Nu a fost bifat sexul");
cmd.Parameters.Add("#Numar", SqlDbType.Int).Value = Convert.ToInt32(textBox11.Text);
cmd.Parameters.Add("#Salariu", SqlDbType.Int).Value = Convert.ToInt32(textBox6.Text);
sqlCon.Open();
cmd.ExecuteNonQuery();
}
}
this.Close();
}
But this is the error I get when I press the button and save everything.
https://i.imgur.com/0tixhsu.png
This is the SQL Server stored procedure:
ALTER PROCEDURE [dbo].[InsertAngajat]
#Nume VARCHAR(50),
#Prenume VARCHAR(50),
#Departament VARCHAR(50),
#cnp CHAR(13),
#DataNasterii DATE,
#Telefon VARCHAR(12) = "NONE",
#DataAngajare DATE,
#Salariu INT,
#Sex CHAR(1) = 'F',
#Judet VARCHAR(50),
#Localitate VARCHAR(50),
#Strada VARCHAR(50),
#Numar INT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #DepID INT = (SELECT D.DepartamentID
FROM Departamente D
WHERE D.[Nume Departament] = #Departament);
INSERT INTO [dbo].Angajat (Nume, Prenume, DepartamentID, CNP, DataNasterii,
Telefon, DataAngajarii, Salariu, Sex, Localitate,
[Sector/Judet], Strada, nr)
VALUES (#Nume, #Prenume, #DepID, #cnp, #DataNasterii,
#Telefon, #DataAngajare, #Salariu, #Sex, #Localitate,
#Judet, #Strada, #Numar)
END
I made sure that the text boxes were having data. I have no idea what else to try.
I'm expecting that as long as the values in the text boxes aren't NULL to be able to Insert all their data easily.
It seems to me that your issue probably lies with this line:
Declare #DepID int = (Select D.DepartamentID From Departamente D Where D.[Nume Departament] = #Departament);
What happens if there are no results for this query? I'm a bit rusty, but I imagine #DepId will be NULL. Then when you try and insert it into your table, you're inserting a null.
Solution: Either in your procedure, or before calling the insert, check if the department exists.
Run your sql profiler and trace the call. So that, you will be sure about your all input parameters. And then execute your procedure call manually. You will be able to find the exact issue and the line in the procedure. Try one with fixed value of #DepID int=1. If it's running successfully. Then you have to optimized this line of code as below:
Declare #DepID int = (Select isnull(D.DepartamentID,0) From Departamente D Where D.[Nume Departament] = #Departament);
It seems your Departamente table don't have data for this department.

Storing a Result (OUTPUT) from a stored procedure into a Gridview c# ASP.Net

I am trying to return the Average value that is generated by a stored procedure into a new column in the Gridview
What should I put instead of the "!!!!" in my code below
I keep getting "Stored procedure expects parameter which was not supplied"
Error although I defined that parameter as OUTPUT in the procedure (BELOW)
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
GridView1.Columns[3].Visible = true;
string Teachername = GridView1.SelectedRow.Cells[1].Text;
string connStr = ConfigurationManager.ConnectionStrings["MS4ConnectionString"].ToString();
SqlConnection conn = new SqlConnection(connStr);
SqlCommand cmd = new SqlCommand("Overall_Rating", conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter Parent_Username = new SqlParameter("#parent_username", TextBox1.Text);
SqlParameter Teacher_Username = new SqlParameter("#teacher_username", Teachername);
SqlParameter Avg = new SqlParameter("#Avg", !!!!);
Avg.Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add(Parent_Username);
cmd.Parameters.Add(Teacher_Username);
cmd.Parameters.Add(Avg);
string retunvalue = (string)cmd.Parameters["#Avg"].Value;
System.Diagnostics.Debug.WriteLine(retunvalue);
conn.Open();
cmd.ExecuteNonQuery();
}
#parent_username varchar(40),
#teacher_username varchar(40),
#Avg smallint output
AS
SET #Avg =
(
select Avg(PRT.rating)
FROM Parents_Rate_Teachers PRT INNER JOIN Employees_Name E ON PRT.teacher_username = E.employee_username
WHERE E.employee_username= #teacher_username
)
return #Avg
I think you just want ParameterDirection.Output instead of ReturnValue:
SqlParameter avg= new SqlParameter();
avg.ParameterName = "#Avg";
avg.Direction = ParameterDirection.Output;
cmd.Parameters.Add(avg);
There are also problem in row (in addition to previous answer)
string retunvalue = (string)cmd.Parameters["#Avg"].Value;
you should return int, because #Avg is smallint (smallint = Int16):
int retunvalue = (int)cmd.Parameters["#Avg"].Value;

Getting null return value from stored procedure

I am trying to get a string return value from a stored procedure, but I am getting null. Stored procedure runs fine and return the expected string (I checked result using SQL Server Profiler) but I get empty string in my code.
public static string GetStringValue(string pCode)
{
String strConnString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
SqlCommand cmd = new SqlCommand();
string returnValue = "";
cmd.CommandText = "usp_GetStringValue";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = new SqlConnection(strConnString);
cmd.Parameters.AddWithValue("#pcode", pCode);
//cmd.Parameters.AddWithValue("#Result", "");
SqlParameter sqlParam = new SqlParameter("#Result", "");
cmd.Parameters.Add(sqlParam);
sqlParam.Direction = ParameterDirection.Output;
cmd.Connection.Open();
cmd.ExecuteScalar();
//cmd.ExecuteNonQuery();
returnValue = Convert.ToString(cmd.Parameters["#Result"].Value);
cmd.Connection.Close();
return returnValue;
}
Here is my Stored Procedure
ALTER PROCEDURE [dbo].[usp_GetStringValue]
#pcode Varchar (4),
#Result varchar(5000) OUTPUT
AS
BEGIN
SET #Result=(Select pPath from mytable where pcode = #pcode)
print #Result
END
Try adding the #Result before adding any other parameters because it's an Output parameter. Rearrange the code as listed below. It's worked for me in the past. I will probably get flamed for this, but it's Friday.
SqlParameter sqlParam = new SqlParameter("#Result", "");
cmd.Parameters.Add(sqlParam);
sqlParam.Direction = ParameterDirection.ReturnValue;
cmd.Parameters.AddWithValue("#pcode", pCode);

Get Return Value from Stored procedure in asp.net

i have a stored procedure
ALTER PROC TESTLOGIN
#UserName varchar(50),
#password varchar(50)
As
Begin
declare #return int;
set #return = (SELECT COUNT(*)
FROM CPUser
WHERE UserName = #UserName
AND Password = #password);
return #return;
End
and in c#
SqlConnection con = db.con;
SqlCommand cmd = new SqlCommand("TESTLOGIN", con);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter parm = new SqlParameter("#return", SqlDbType.Int);
parm.Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add(parm);
cmd.Parameters.Add(new SqlParameter("#UserName", txtUserName.Text.ToString().Trim()));
cmd.Parameters.Add(new SqlParameter("#password", txtPassword.Text.ToString().Trim()));
cmd.ExecuteNonQuery();
con.Close();
int id = Convert.ToInt32(parm.Value);
but it always return 0. Please help me to solve this problem
You need a parameter with Direction set to ParameterDirection.ReturnValue in code but no need to add an extra parameter in SP. Try this
SqlParameter returnParameter = cmd.Parameters.Add("RetVal", SqlDbType.Int);
returnParameter.Direction = ParameterDirection.ReturnValue;
cmd.ExecuteNonQuery();
int id = (int) returnParameter.Value;
2 things.
The query has to complete on sql server before the return value is sent.
The results have to be captured and then finish executing before
the return value gets to the object.
In English, finish the work and then retrieve the value.
this will not work:
cmm.ExecuteReader();
int i = (int) cmm.Parameters["#RETURN_VALUE"].Value;
This will work:
SqlDataReader reader = cmm.ExecuteReader();
reader.Close();
foreach (SqlParameter prm in cmd.Parameters)
{
Debug.WriteLine("");
Debug.WriteLine("Name " + prm.ParameterName);
Debug.WriteLine("Type " + prm.SqlDbType.ToString());
Debug.WriteLine("Size " + prm.Size.ToString());
Debug.WriteLine("Direction " + prm.Direction.ToString());
Debug.WriteLine("Value " + prm.Value);
}
if you are not sure
check the value of the parameter
before during and after the results have been processed by the reader.
you can try this.Add the parameter as output direction and after executing the query get the output parameter value.
SqlParameter parmOUT = new SqlParameter("#return", SqlDbType.Int);
parmOUT.Direction = ParameterDirection.Output;
cmd.Parameters.Add(parmOUT);
cmd.ExecuteNonQuery();
int returnVALUE = (int)cmd.Parameters["#return"].Value;
Procedure never returns a value.You have to use a output parameter in store procedure.
ALTER PROC TESTLOGIN
#UserName varchar(50),
#password varchar(50)
#retvalue int output
as
Begin
declare #return int
set #return = (Select COUNT(*)
FROM CPUser
WHERE UserName = #UserName AND Password = #password)
set #retvalue=#return
End
Then you have to add a sqlparameter from c# whose parameter direction is out.
Hope this make sense.
If you want to to know how to return a value from stored procedure to Visual Basic.NET. Please read this tutorial: How to return a value from stored procedure
I used the following stored procedure to return the value.
CREATE PROCEDURE usp_get_count
AS
BEGIN
DECLARE #VALUE int;
SET #VALUE=(SELECT COUNT(*) FROM tblCar);
RETURN #VALUE;
END
GO
Do it this way (make necessary changes in code)..
SqlConnection con = new SqlConnection(GetConnectionString());
con.Open();
SqlCommand cmd = new SqlCommand("CheckUser", con);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter p1 = new SqlParameter("username", username.Text);
SqlParameter p2 = new SqlParameter("password", password.Text);
cmd.Parameters.Add(p1);
cmd.Parameters.Add(p2);
SqlDataReader rd = cmd.ExecuteReader();
if(rd.HasRows)
{
//do the things
}
else
{
lblinfo.Text = "abc";
}

Categories