Consider this code....
WHY is it failing telling me that the #PI_CDID parameter value is not set when trying to execute the stored procedure?
Console.WriteLine("Database Opened!");
SqlCommand cmd = new SqlCommand("P_IOU_Track", conn);
cmd.Parameters.Add(new SqlParameter("#PI_CDID", ICDID)); // parameter is added here
cmd.Parameters.Add(new SqlParameter("#PI_Title", ITitle));
cmd.Parameters.Add(new SqlParameter("#PI_Duration", IDuration));
cmd.Parameters.Add(new SqlParameter("#PI_CDNo", ICDNo));
cmd.Parameters.Add(new SqlParameter("#PI_TNo", ITNo));
foreach (SqlParameter p in cmd.Parameters )
{
Console.WriteLine("Parameter , {0} , Value --> {1} ",p.ParameterName, p.Value.ToString());
}
// Add output param
SqlParameter NextTID = new SqlParameter("#PO_NextTID", SqlDbType.BigInt);
NextTID.Direction = ParameterDirection.Output;
cmd.Parameters.Add(NextTID);
// Execute procedure
cmd.ExecuteNonQuery();
You forgot cmd.CommandType = CommandType.StoredProcedure
Related
Using this code to update a record
var query = "UPDATE myTable SET name = #name where id = #id";
using (DbCommand cmd = new OleDbCommand(query, connection))
{
try
{
cmd.Parameters.Add(new OleDbParameter("#id", item.Id));
cmd.Parameters.Add(new OleDbParameter("#name", item.Name));
cmd.ExecuteNonQuery();
}
catch (Exception e) { }
}
But the record does not get updated. I get no error. The record exists in the DB. What is going on?
I don't know why but you have to add the parameters of your query in the order they appear in your query string. So flip these two lines
cmd.Parameters.Add(new OleDbParameter("#id", item.Id));
cmd.Parameters.Add(new OleDbParameter("#name", item.Name));
to
cmd.Parameters.Add(new OleDbParameter("#name", item.Name));
cmd.Parameters.Add(new OleDbParameter("#id", item.Id));
I've been advised to replace my code with SqlParameter to avoid SQL injection as a security issue but with my limited understanding. I tried implementing it but I'm faced with an error:
Must Declare Scalar Variable
I've tried the other suggestions of other threads about implementing a new parameter for every insertion instead of replacing the value of parameter for every entry.
String query = "INSERT INTO EmpInfo(EmpYear, EmpStatus, LName, FName, JobTitle, EmpPay, EmpDoB, EmpSex, EmpAddr, EmpCity, EmpState, EmpZIP, EmpCountry, EmpEAddr, EmpTelNo, EmpMobileNo, EmpDate) " +
"VALUES('"+EmpYear+"', #EmpStatus, #LName, #FName, #JobTitle, #EmpPay, #EmpDoB, #EmpSex, #EmpAddr, #EmpCity, #EmpState, #EmpZIP, #EmpCountry, #EmpEAddr, #EmpTelNo, #EmpMobileNo, getdate())";
String query2 = "INSERT INTO AccountInfo(LName, FName, EmpTemplate, AccountType, EmpStatus, EmpDate) " +
"VALUES (#LName, #FName, #EmpTemplate, #AccountType, #EmpStatus, GetDate())";
using (SqlConnection connection = new SqlConnection("Data Source=RB-DESKTOP;Initial Catalog=TimeDB;Persist Security Info=True;User ID=sa;Password=bautista7"))
{
SqlCommand cmd = new SqlCommand(query, connection);
cmd.Connection = conn;
conn.Open();
cmd.CommandText = "SELECT MAX(EmpID) FROM EmpInfo";
SqlDataReader rdr = cmd.ExecuteReader();
rdr.Close();
SqlCommand command = new SqlCommand(query, cmd.Connection);
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpYear", Value = EmpYear });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpStatus", Value = "Active" });
command.Parameters.Add(new SqlParameter() { ParameterName = "#LName", Value = regLname_text.Text });
command.Parameters.Add(new SqlParameter() { ParameterName = "#FName", Value = regFname_text.Text });
command.Parameters.Add(new SqlParameter() { ParameterName = "#JobTitle", Value = "NULL" });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpPay", Value = PayType_cb.SelectedItem.ToString() });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpDoB", Value = regDob_dtp.Value.Date });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpSex", Value = gender });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpAddr", Value = regAddr_text.Text });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpCity", Value = regCity_text.Text });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpState", Value = regState_text.Text });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpZIP", Value = regZip_text.Text });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpCountry", Value = regCountry_text.Text });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpEAddr", Value = regEmail_text.Text });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpTelNo", Value = regTel_text.Text });
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpMobileNo", Value = regMob_text.Text });
command.ExecuteNonQuery();
command.Parameters.Clear();
SqlCommand command2 = new SqlCommand(query2, cmd.Connection);
command.Parameters.AddWithValue("#LName", regLname_text.Text);
command.Parameters.AddWithValue("#FName", regFname_text.Text);
command.Parameters.AddWithValue("#EmpTemplate", template);
command.Parameters.AddWithValue("#AccountType", AcctType_cb.SelectedItem.ToString());
command.Parameters.AddWithValue("#EmpStatus", "Active");
command.ExecuteNonQuery();
command.Parameters.Clear();
You are using the command variable twice instead of command2 after you create command2. You get the error because you cleared command of all parameters, then add parameters (which do not match the existing query) and then execute ExecuteNonQuery which then throws the error.
Change 2nd execution statement / command like so, notice that after the creation of command2 it is now also used instead of reusing command.
SqlCommand command2 = new SqlCommand(query2, cmd.Connection);
command2.Parameters.AddWithValue("#LName", regLname_text.Text);
command2.Parameters.AddWithValue("#FName", regFname_text.Text);
command2.Parameters.AddWithValue("#EmpTemplate", template);
command2.Parameters.AddWithValue("#AccountType", AcctType_cb.SelectedItem.ToString());
command2.Parameters.AddWithValue("#EmpStatus", "Active");
var numberOfRecordsInserted = command2.ExecuteNonQuery();
// value of numberOfRecordsInserted should be 1
Also when you are done using a SqlCommand you can dispose of it, there is no need to call SqlCommand.Parameters.Clear() unless you plan on reusing the exact same SqlCommand instance which you are not (at least not in the posted code).
I think you should try simplify your logic first. I found several weird things.
query has "VALUES('"+EmpYear+"', I think you want #EmpYear because you also have
command.Parameters.Add(new SqlParameter() { ParameterName = "#EmpYear", Value = EmpYear });
Additionally
SqlCommand cmd = new SqlCommand(query, connection);
//^^^ here you use insert query
cmd.Connection = conn;
conn.Open();
cmd.CommandText = "SELECT MAX(EmpID) FROM EmpInfo"; // But here you change it for a SELECT?
// Then you execeute a DataReader but you close it before save the result.
SqlDataReader rdr = cmd.ExecuteReader();
rdr.Close();
//Then create the insert command again
SqlCommand commad = new SqlCommand(query, cmd.Connection);
....
// clear command, I guess you want reuse it
command.Parameters.Clear();
// now create command 2 is OK
SqlCommand command2 = new SqlCommand(query2, cmd.Connection);
// ^^^ second insert query
// but add parameteres to command NOT OK
command.Parameters.AddWithValue("#LName", regLname_text.Text);
I have an update query(stored procedure) which is working properly in SQL Server when I execute it.
CREATE PROCEDURE updatestudenthws(#stdid nvarchar(50),#hwid int, #grade float)
AS
UPDATE Table_Exercise_Answer
SET
ExAns_Grade = #grade
WHERE ExAns_Exercise = #hwid AND ExAns_Student = #stdid
but when I run the program it does not have any effect in my table and also I don't have any error.
con.Open();
SqlCommand cmd = new SqlCommand("updatestudenthws", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#hwid", SqlDbType.VarChar);
cmd.Parameters.Add("#stdid", SqlDbType.VarChar);
cmd.Parameters.Add("#grade", SqlDbType.VarChar);
cmd.Parameters["#hwid"].Value = hwid;
cmd.Parameters["#stdid"].Value = studentid;
cmd.Parameters["#grade"].Value = grade;
cmd.ExecuteNonQuery();
con.Close();
What is my mistake?
How should I do this work?
Use AddWithValue(), so you don't have to provide the type, which allowed you to make the mistake of passing varchar to an int parameter.
con.Open();
SqlCommand cmd = new SqlCommand("updatestudenthws", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#hwid", hwid);
cmd.Parameters.AddWithValue("#stdid", studentid);
cmd.Parameters.AddWithValue("#grade", grade);
cmd.ExecuteNonQuery();
con.Close();
Your ADO.NET code defining the parameters for the stored procedure is wrong in that you don't define the parameters with their proper datatypes.
Your stored procedure defines:
#stdid nvarchar(50) --> but you define it as varchar
#hwid int --> but you define it as varchar
#grade float --> but you define it as varchar
You need to change your code to this:
SqlCommand cmd = new SqlCommand("updatestudenthws", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#hwid", SqlDbType.Int); // this needs to be SqlDbType.Int
cmd.Parameters.Add("#stdid", SqlDbType.NVarChar, 50); // this should be SqlDbType.NVarChar and specify its proper length
cmd.Parameters.Add("#grade", SqlDbType.Float); // this needs to be SqlDbType.Float
when you use AddWithValue(), don't you have to provide the type passing like varchar to an int parameter.
con.Open();
SqlCommand cmd = new SqlCommand("updatestudenthws", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#hwid", hwid);
cmd.Parameters.AddWithValue("#stdid", studentid);
cmd.Parameters.AddWithValue("#grade", grade);
cmd.ExecuteNonQuery();
con.Close();
I have made a function like this
public int InsertData(CategoryPhoto catphoto)
{
string ans = null;
SqlCommand cmd = DataConnection.GetConnection().CreateCommand();
cmd.CommandText = "prcCategoryPhoto";
cmd.CommandType = CommandType.StoredProcedure;
// cmd.Parameters.Add(new SqlParameter("#PhotoID", prdctphoto.PhotoID));
cmd.Parameters.Add(new SqlParameter("#PhotoName", catphoto.PhotoName));
//cmd.Parameters.Add(new SqlParameter("#LeftPhoto", prdctphoto.LeftPhoto));
//cmd.Parameters.Add(new SqlParameter("#RightPhoto", prdctphoto.RightPhoto));
//cmd.Parameters.Add(new SqlParameter("#BackPhoto", prdctphoto.BackPhoto));
//cmd.Parameters.Add(new SqlParameter("#MaterialPhoto", prdctphoto.MaterialPhoto));
cmd.Parameters.Add(new SqlParameter("#ExtName", catphoto.ExtName));
cmd.Parameters.Add(new SqlParameter("#PhotoType", catphoto.PhotoType));
cmd.Parameters.Add(new SqlParameter("#PhotoSize", catphoto.PhotoSize));
cmd.Parameters.Add(new SqlParameter("#CategoryID", catphoto.CategoryID));
ans = cmd.ExecuteScalar().ToString();
//var result = cmd.ExecuteScalar();
//ans = int.Parse(result.ToString());
cmd.Dispose();
DataConnection.CloseConnection();
return ans;
}
In my stored procedure is
create proc [dbo].[prcCategoryPhoto]
(
#PhotoName Varchar(100),
#ExtName Varchar(100),
#PhotoType Varchar(100),
#PhotoSize int,
#CategoryID varchar(20)
)
as
insert into CategoryPhoto(PhotoName,ExtName,PhotoType,PhotoSize,CategoryID)
values (#PhotoName,#ExtName,#PhotoType,#PhotoSize,#CategoryID)
select ##IDENTITY
on writing return ans it is giving a error
can not implicitly convert string to int
and on writing
return int.Parse(ans);
it gives exception that nvarchar cannot be converted to int
now try this....
`
public string InsertData(CategoryPhoto catphoto)
{
string ans = null;
SqlCommand cmd = DataConnection.GetConnection().CreateCommand();
cmd.CommandText = "prcCategoryPhoto";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#PhotoName", catphoto.PhotoName));
cmd.Parameters.Add(new SqlParameter("#ExtName", catphoto.ExtName));
cmd.Parameters.Add(new SqlParameter("#PhotoType", catphoto.PhotoType));
cmd.Parameters.Add(new SqlParameter("#PhotoSize", catphoto.PhotoSize));
cmd.Parameters.Add(new SqlParameter("#CategoryID", catphoto.CategoryID));
ans = cmd.ExecuteScalar().ToString();
cmd.Dispose();
DataConnection.CloseConnection();
return ans;
}`
try below,
first alter your procedure, add a output parameter as below,
create proc [dbo].[prcCategoryPhoto]
(
#PhotoName Varchar(100),
#ExtName Varchar(100),
#PhotoType Varchar(100),
#PhotoSize int,
#CategoryID varchar(20),
#ID INT OUTPUT
)
as
insert into CategoryPhoto(PhotoName,ExtName,PhotoType,PhotoSize,CategoryID)
values (#PhotoName,#ExtName,#PhotoType,#PhotoSize,#CategoryID)
select #ID = ##IDENTITY
Next modify your function as below,
public int InsertData(CategoryPhoto catphoto)
{
SqlCommand cmd = DataConnection.GetConnection().CreateCommand();
cmd.CommandText = "prcCategoryPhoto";
cmd.CommandType = CommandType.StoredProcedure;
// cmd.Parameters.Add(new SqlParameter("#PhotoID", prdctphoto.PhotoID));
cmd.Parameters.Add(new SqlParameter("#PhotoName", catphoto.PhotoName));
//cmd.Parameters.Add(new SqlParameter("#LeftPhoto", prdctphoto.LeftPhoto));
//cmd.Parameters.Add(new SqlParameter("#RightPhoto", prdctphoto.RightPhoto));
//cmd.Parameters.Add(new SqlParameter("#BackPhoto", prdctphoto.BackPhoto));
//cmd.Parameters.Add(new SqlParameter("#MaterialPhoto", prdctphoto.MaterialPhoto));
cmd.Parameters.Add(new SqlParameter("#ExtName", catphoto.ExtName));
cmd.Parameters.Add(new SqlParameter("#PhotoType", catphoto.PhotoType));
cmd.Parameters.Add(new SqlParameter("#PhotoSize", catphoto.PhotoSize));
cmd.Parameters.Add(new SqlParameter("#CategoryID", catphoto.CategoryID));
cmd.Parameters.Add(new SqlParameter("#ID",System.Data.SqlDbType.Int));
cmd.Parameters["#ID"].Direction=System.Data.ParameterDirection.Output;
cmd.ExecuteNonQuery();
var ans = cmd.Parameters["#ID"].Value;
cmd.Dispose();
DataConnection.CloseConnection();
return Convert.ToInt32(ans);
}
Look at your string (ans) in debugger. Seems like you have some characters that can not be converted to int. Can you change the return type of the method from int to string?
You should be using the using keyword. It makes sure that the dispose method is called even if something goes wrong (i.e. and exception is raised).
Also, the ##Identity returns a numeric value in any case (according to MSDN), which should be convertible to an integer or a bigint. So my suggestion would be:
public Int64 InsertData(CategoryPhoto catphoto)
{
using (var connection = DataConnection.GetConnection)
{
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = "prcCategoryPhoto";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#PhotoName", catphoto.PhotoName));
cmd.Parameters.Add(new SqlParameter("#ExtName", catphoto.ExtName));
cmd.Parameters.Add(new SqlParameter("#PhotoType", catphoto.PhotoType));
cmd.Parameters.Add(new SqlParameter("#PhotoSize", catphoto.PhotoSize));
cmd.Parameters.Add(new SqlParameter("#CategoryID", catphoto.CategoryID));
return (Int64)cmd.ExecuteScalar();
}
}
}
In case your identity-column is an integer, you may of course change the signature of the method to return an int instead.
Replace
public int InsertData(CategoryPhoto catphoto)
with
public string InsertData(CategoryPhoto catphoto)
and follow the same for its dependancies...
The ScoapIdentity will return your primarykey value , So that datatype is int , So you need to declare to int variable(not a string variable) .
So Replace this line string ans = null; to int ans = null;
and also need to change this below line
ans = Convert.ToInt32(cmd.ExecuteScalar());
I have stored procedure, which works great in MS SQL management studio.
When I try to use it in VS rows returns fine, but value of output parameters is NULL.
SqlCommand cmd = new SqlCommand("proc_name", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#p_SomeVal", SqlDbType.Int));
cmd.Parameters["#p_SomeVal"].Direction = ParameterDirection.Output;
rdr = cmd.ExecuteReader();
//...process rows...
if (cmd.Parameters["#p_SomeVal"].Value != null)
SomeVal = (int)cmd.Parameters["#p_SomeVal"].Value;
cmd.ExecuteNonQuery(); Has the same result.
USE [db_name]
GO
DECLARE #return_value int,
#p_SomeValue int
EXEC #return_value = [dbo].[Proc_name]
#p_InputVal = N'aa',
#p_SomeValue = #p_SomeValue OUTPUT
SELECT #p_SomeValue as N'p_SomeValue'
SELECT 'Return Value' = #return_value
GO
SqlCommand cmd = new SqlCommand("proc_name", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#p_SomeVal", SqlDbType.Int));
cmd.Parameters["#p_SomeVal"].Direction = ParameterDirection.Output;
rdr = cmd.ExecuteReader();
//...process rows...
rdr.Close();
if (cmd.Parameters["#p_SomeVal"].Value != null)
SomeVal = (int)cmd.Parameters["#p_SomeVal"].Value;
After procesing rows I added rdr.Close(); and worked fine.
Salaam,
You can check if output is null and convert like this.
returnedSQLParameter.Value != DBNull.Value? (int)returnedSQLParameter.Value : 0;
Because it is returning DBNull.value when output sent NULL from stored procedure.