I am attempting to run a stored procedure and add the results to a data table. My stored procedure executes as it should, bc if I query the table the results are stored in from SSMS - the accurate results are there. However, my code below will produce numberofrecords = 0 everytime!
What did I set-up incorrectly in this syntax below?
using (conn = new SqlConnection(SQLConn))
{
using (cmd = new SqlCommand(storedprocname, conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#Name", SqlDbType.VarChar, 100);
cmd.Parameters.Add("d1", SqlDbType.Date, 100);
cmd.Parameters.Add("d2", SqlDbType.Date, 100);
cmd.Parameters["#Name"].Value = cboNames.Text.ToString();
cmd.Parameters["d1"].Value = dtpd1.Value.ToString("MM/dd/yyyy");
cmd.Parameters["d2"].Value = dtpd2.Value.ToString("MM/dd/yyyy");
cmd.Parameters.Add("#Dolla", SqlDbType.VarChar, 100);
cmd.Parameters["#Dolla"].Value = cboDolla.Text.ToString();
using (da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
int numberOfRecords = 0;
numberOfRecords = dt.Select().Length;
MessageBox.Show(numberOfRecords.ToString());
}
And these are my class variable declarations:
public static SqlCommand cmd;
public static SqlDataAdapter da;
public static DataSet ds = new DataSet();
public static DataTable dt = new DataTable();
EDIT
And this is my stored proc which produces roughly 32 rows
ALTER Procedure [dbo].[TestParamQuery]
(
#Name varchar(max)
,#d1 varchar(100)
,#d2 varchar(100)
,#dolla varchar(500)
)
As
Select
EmployeeName
,EmployeeNumber
,CAST(hiredate As Date) [hire date]
,saleamount
FROM [TestDB].[dbo].[SalesFigs]
WHERE employeename = #Name
AND hiredate between #d1 AND #d2
AND saleamount >= #dolla
EDIT 2
This is how I execute the stored procedure to ensure it is returning the results I want from directly inside SSMS
USE [TestDB]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[TestParamQuery]
#Name = N'Sam Wise',
#d1 = N'03/01/2016',
#d2 = N'01/30/2016',
#Dolla = N'1000'
SELECT 'Return Value' = #return_value
GO
Unfortunately, SqlCommand does not have an easy method or property for converting the command to a string, with all parameters and values included. I have used a method like this in the past to make debugging commands easier:
public static string PrintCommand(this SqlCommand command){
if (command == null) throw new ArgumentNullException("command");
var sb = new StringBuilder();
sb.AppendLine(command.CommandText);
foreach (var p in command.Parameters){
sb.AppendLine("\t" + p.ParameterName + ": " + p.Value);
}
return sb.ToString();
}
It should output a string like this:
"dbo.MyCommandName
#Name: myNameParameterValue
d1: 01/01/2016
d2: 02/02/2016
#Dolla: myDollaValue"
You can then invoke it like this, and check the value in a step-thru debugger.
using (conn = new SqlConnection(SQLConn))
using (cmd = new SqlCommand(storedprocname, conn)) {
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#Name", SqlDbType.VarChar, 100);
cmd.Parameters.Add("d1", SqlDbType.Date, 100);
cmd.Parameters.Add("d2", SqlDbType.Date, 100);
cmd.Parameters["#Name"].Value = cboNames.Text.ToString();
cmd.Parameters["d1"].Value = dtpd1.Value.ToString("MM/dd/yyyy");
cmd.Parameters["d2"].Value = dtpd2.Value.ToString("MM/dd/yyyy");
cmd.Parameters.Add("#Dolla", SqlDbType.VarChar, 100);
cmd.Parameters["#Dolla"].Value = cboDolla.Text.ToString();
//Get a text representation here:
var text = cmd.PrintCommand();
//Put a breakpoint here to check the value:
using (da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
int numberOfRecords = 0;
numberOfRecords = dt.Select().Length;
MessageBox.Show(numberOfRecords.ToString());
}
Not sure why you cannot get values. But anyway please try this approach:
using (conn = new SqlConnection(SQLConn))
using (cmd = new SqlCommand(storedprocname, conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Name", cboNames.Text);
cmd.Parameters.AddWithValue("d1", dtpd1.Value.ToShortDateString();
cmd.Parameters.AddWithValue("d2", dtpd2.Value.ToShortDateString();
cmd.Parameters.AddWithValue("#Dolla", cboDolla.Text);
using (da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
var numberOfRecords = dt.Rows.Count;
MessageBox.Show(numberOfRecords);
}
Related
So far I managed to use Insert command to create a new record inside a table called "Students". This is the code i used:
int ID = int.Parse( TextBox1.Text);
string name = TextBox2.Text;
string gender = TextBox3.Text;
int marks = int.Parse(TextBox4.Text);
string CS = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
using (SqlConnection con = new SqlConnection(CS))
{
//create data adapter
SqlDataAdapter adapter = new SqlDataAdapter("select * from students",con);
//create sqlcommand to store execute stored procedure
adapter.InsertCommand = new SqlCommand("spInsertStudent",con);
adapter.InsertCommand.CommandType = CommandType.StoredProcedure;
//create parameter for Return value (#ROWCOUNT)
SqlParameter parameter = adapter.InsertCommand.Parameters.Add("#ROWCOUNT",SqlDbType.Int);
parameter.Direction = ParameterDirection.ReturnValue;
adapter.InsertCommand.Parameters.Add("#ID", SqlDbType.Int, 0, "ID");
adapter.InsertCommand.Parameters.Add("#Name",SqlDbType.NVarChar,50,"Name");
adapter.InsertCommand.Parameters.Add("#Gender",SqlDbType.NVarChar,10,"Gender");
adapter.InsertCommand.Parameters.Add("#TotalMarks",SqlDbType.Int,0,"TotalMarks");
DataSet ds = new DataSet();
//DataTable students = new DataTable();
adapter.Fill(ds,"Students");
DataTable students = ds.Tables["Students"];
DataRow studentRow = students.NewRow();
studentRow["ID"] = ID;
studentRow["Name"] = name;
studentRow["Gender"] = gender;
studentRow["TotalMarks"] = marks;
students.Rows.Add(studentRow);
adapter.Update(ds,"Students");
Now I want to edit a data row. The data will be change if the ID is matched with the ID parameter. This is the stored procedure I'm using:
create procedure updateStudent
#ID int,
#Name varchar(50),
#Gender varchar(10),
#TotalMarks int
AS
BEGIN
update Students set Name = #Name, Gender = #Gender, TotalMarks = #TotalMarks
where ID = #ID
END
and this is the C# code i use in the code behind:
int ID = int.Parse(TextBox1.Text);
string name = TextBox2.Text;
string gender = TextBox3.Text;
int marks = int.Parse(TextBox4.Text);
string CS = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
using (SqlConnection con = new SqlConnection(CS))
{
SqlDataAdapter adapter = new SqlDataAdapter("Select * from Students",con);
DataTable dtStudents = new DataTable();
adapter.Fill(dtStudents);
SqlCommand cmd = new SqlCommand("updateStudent",con);
cmd.Parameters.Add("#ID", SqlDbType.Int, 0, "ID").Value = ID;
cmd.Parameters.Add("#Name", SqlDbType.NVarChar, 50, "Name").Value = name;
cmd.Parameters.Add("#Gender", SqlDbType.NVarChar, 10, "Gender").Value = gender;
cmd.Parameters.Add("#TotalMarks", SqlDbType.Int, 0, "TotalMarks").Value = marks;
adapter.UpdateCommand = cmd;
adapter.Update(dtStudents);
}
But after I clicked the Update button on my web form, there is no error message and the data didn't get updated in my database. What have I did wrong here?
I think you should write classes for executing stored procedures. It will be more easier to read and handle. RunQuery method in such a class like DB
private SqlConnection Connection;
public bool Open()
{
try
{
ConnectionString = "your connection string";
Connection = new SqlConnection(ConnectionString);
Connection.Open();
return true;
}
catch (Exception ex)
{
errorMessage = ex.Message;
return false;
}
}
public bool RunQuery(string ProcedureName, SqlParameter[] Parameters)
{
bool res = false;
try
{
SqlCommand Command = new SqlCommand();
Command.CommandText = ProcedureName;
Command.CommandType = CommandType.StoredProcedure;
Command.Connection = Connection;
Command.Parameters.AddRange(Parameters);
Command.ExecuteNonQuery();
res = true;
}
catch (Exception ex)
{
throw ex;
}
return res;
}
And you can call it
SqlParameter[] param= new SqlParameter[4];
param[0] = new SqlParameter("#ID", ID);
param[1] = new SqlParameter("#Name", name);
param[2] = new SqlParameter("#Gender", gender);
param[3] = new SqlParameter("#TotalMarks", marks);
RunQuery("updateStudent", param);
public DataTable GetRandomQuestionByCateId(string id, int z)
{
string sql = "SELECT * FROM tblQuestions where CategoryId=#a ORDER BY QId OFFSET #z ROWS FETCH NEXT 1 ROWS ONLY";
SqlParameter[] param = new SqlParameter[]
{
new SqlParameter("#a",id),
new SqlParameter("#z",z),
};
return DAO.GetTable(sql, param);
}
I have this code segment and want to execute a stored procedure as:
CREATE PROCEDURE GetRandomQuest
(#a int,
#b int)
AS
BEGIN
SET NOCOUNT ON;
SELECT *
FROM tblQuestions
WHERE CategoryId = #a
ORDER BY QId
OFFSET #b ROWS
FETCH NEXT 1 ROWS ONLY;
END
EXEC dbo.GetRandomQuest `#a=2`, `#b=1`
How can I replace it in above case?
Actually the execusion is happening inside the DAO.GetTable() method but it is not provided in the question, no problem, you can modify the signature of the GetRandomQuestionByCateId to execute stored procedure instead of sqlquery. the changes will be like the following:
public DataTable GetRandomQuestionByCateId(string id, int z)
{
DataTable resultData;
String sqlProcedure = "GetRandomQuest";
using (SqlConnection cn = new SqlConnection("Your connection string here"))
{
using (SqlCommand cmd = new SqlCommand(sql, cn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#a", SqlDbType.VarChar, 50).Value = a;
cmd.Parameters.Add("#z", SqlDbType.int).Value = z;
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(resultData);
}
}
return resultData;
}
Key points to note, by using cmd.CommandType = CommandType.StoredProcedure; you are specifying that you wanted to execute a stored procedure, in this case the commandText will be the name of the procedure and you can add parameters to the command as like what you are doing currently.
Use this code:
public DataTable GetRandomQuestionByCateId(string id, int z)
{
var conn = new SqlConnection(connectionString);
var cmd = new SqlCommand("GetRandomQuest", conn) ;
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add("#a", SqlDbType.VarChar).Value = id;
cmd.Parameters.Add("#b", SqlDbType.VarChar).Value = z;
conn.Open();
DataTable dt = new DataTable();
dt.Load(cmd.ExecuteReader());
return dt;
}
public DataTable GetRandomQuestion(int id, int z)
{
ArrayList sqlParameterArrayList = new ArrayList();
SqlParameter sqpID = new SqlParameter("a", SqlDbType.Int);
sqpID.Value = id;
sqlParameterArrayList.Add(sqpID);
SqlParameter sqpZ = new SqlParameter("b", SqlDbType.Int);
sqpZ.Value = z;
sqlParameterArrayList.Add(sqpZ);
return DAO.GetTable("GetRandomQuest", sqlParameterArrayList);
}
I changed the datatype for id to int because that's what you're expecting in your stored procedure. Just do those changes as required. Hope this helps.
In my C# code I am using :
public void Add(int ID)
{
foreach (AccessoireToSell item in OrderToAdd.Accessoires)
{
Adder(item.Ref, item.Qte, item.SellPrice, ID);
}
}
private void Adder(int refid,int Qtetosell,string sellprice,int ID)
{
SqlParameter[] param = new SqlParameter[4];
param[0] = new SqlParameter("#AccessoireID", SqlDbType.Int);
param[0].Value = refid;
param[1] = new SqlParameter("#Qte", SqlDbType.Int);
param[1].Value = Qtetosell;
param[2] = new SqlParameter("#Price", SqlDbType.VarChar, 50);
param[2].Value = sellprice;
param[3] = new SqlParameter("#ORDERID", SqlDbType.Int);
param[3].Value = ID;
Function.Execute(param, "AccessoiresAddOrder");
}
The procedure AccessoiresAddOrder :
ALTER PROCEDURE [dbo].[AccessoiresAddOrder]
#ORDERID int,
#AccessoireID int,
#Qte int,
#Price Varchar(50)
AS
INSERT INTO [dbo].[Accessoires_OrderDetails] ([orderID], [AccessoireID],[Qte], [Price])
VALUES (#ORDERID, #AccessoireID, #Qte, #Price)
I don't understand why the records get inserted 2 times in a row. For example I insert a row from the Datagridview and I get the same row twice in my SQL Server table.
Please note that I checked the AccessoireToSell list counts during the execution as well it say for "Count = 2" in my table I find 4 records.
Execute method :
public void Execute(SqlParameter[] param, string ProcName)
{
SqlCommand Cmd = new SqlCommand();
Cmd.CommandText = ProcName;
Cmd.CommandType = CommandType.StoredProcedure;
if (param != null)
{
Cmd.Parameters.AddRange(param);
}
Cmd.Connection = Base.Connection;
if (Base.Status() == true)
Cmd.ExecuteNonQuery();
else
Base.Open();
Cmd.ExecuteNonQuery();
}
Use this code:-
if (Base.Status() == true)
Cmd.ExecuteNonQuery();
else
{
Base.Open();
Cmd.ExecuteNonQuery();
}
The difference is just add curly braces {....} to the else clause. The code without curly braces {} is executing the Cmd.ExecuteNonQuery() call twice.
I'm beginner in C# and SQL Server, and I wrote this query for creating a stored procedure in SQL Server:
create procedure newBehzad
#id bigint
as
DECLARE #ResultValue int
select *
from TABLEA
where id > #id
SET #ResultValue = -5
go
Everything is working, and I wrote this C# code to call that stored procedure and it return a single value:
using (var conn = new SqlConnection(connectionString))
using (var command = new SqlCommand("newBehzad", conn)
{
CommandType = CommandType.StoredProcedure
})
{
conn.Open();
command.Parameters.Add("#id", SqlDbType.BigInt).Value = 2;
command.Parameters.Add("#ResultValue", SqlDbType.Int);
SqlParameter retval = command.Parameters.Add("#ResultValue", SqlDbType.Int);
retval.Direction = ParameterDirection.ReturnValue;
retunvalue = (string)command.Parameters["#ResultValue"].Value;
//SqlParameter retval = sqlcomm.Parameters.Add("#b", SqlDbType.VarChar);
command.ExecuteNonQuery();
conn.Close();
}
MessageBox.Show(returnValue);
But when I run the C# windows application, I get this error:
Procedure or function newBehzad has too many arguments specified.
How can I solve that? Thanks.
Change you procedure to:
create procedure newBehzad #id bigint, #ResultValue int OUT
as
SET #ResultValue = 0
BEGIN
select *from TABLEA
where id>#id
SET #ResultValue = -5
END
go
Please try somethink like this:
object returnValue = null;
using (var conn = new System.Data.SqlClient.SqlConnection(AbaseDB.DBFactory.GetInstance().GetConnectionString()))
{
using (System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand("newBehzad", conn) { CommandType = CommandType.StoredProcedure })
{
conn.Open();
command.Parameters.Add("#id", SqlDbType.BigInt).Value = 2;
command.Parameters.Add("#ResultValue", SqlDbType.Int).Direction = ParameterDirection.Output;
command.ExecuteNonQuery();
returnValue = command.Parameters["#ResultValue"].Value;
conn.Close();
}
if (returnValue != null)
MessageBox.Show(returnValue.ToString());
}
using (var conn = new SqlConnection(connectionString))
using (var command = new SqlCommand("newBehzad", conn)
{
CommandType = CommandType.StoredProcedure
})
{
conn.Open();
command.Parameters.Add("#id", SqlDbType.BigInt).Value = 2;
// command.Parameters.Add("#ResultValue", SqlDbType.Int); Comment this line
SqlParameter retval = command.Parameters.Add("#ResultValue", SqlDbType.Int);
retval.Direction = ParameterDirection.ReturnValue;
retunvalue = (string)command.Parameters["#ResultValue"].Value;
//SqlParameter retval = sqlcomm.Parameters.Add("#b", SqlDbType.VarChar);
command.ExecuteNonQuery();
conn.Close();
}
MessageBox.Show(returnValue);
First of all you need to change the stored proc to return the value:
create procedure newBehzad #id bigint
as
DECLARE #ResultValue int
select *from TABLEA
where id>#id
SET #ResultValue = -5
Return #ResultValue
go
Then grab it with:
using (var conn = new SqlConnection(connectionString))
{
conn.Open();
using (var cmd = new SqlCommand("newBehzad", conn)
{
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter retval = new SqlParameter();
retval.Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add("#id", SqlDbType.BigInt).Value = 2;
cmd.Parameters.Add(retval);
cmd.ExecuteNonQuery();
returnValue = (int)retval.Value;
}
}
But I really can not get why are you selecting data in the stored proc...
I have the following code that matches user input via session variables. The Stored Procedure returns the Row Count if the data in the Session Variable matches the data in the database.
Everything works except I want to return the Row Count which will always be a single row:
In a nutshell, you visit a form, add info and hit submit. The data is stored in session and the stored procedure returns the data when matched.
Even though the program works the intRecCount variable is always zero rather than the row count.
Stored Procedure:
CREATE PROCEDURE [dbo].[uspConfirmation]
#RecordID CHAR(36),
#LName VARCHAR(30),
#FName VARCHAR(30),
#MInit CHAR(1),
#RecordCount INT OUTPUT
AS
SELECT * FROM Registration
WHERE RecordID = #RecordID AND
LName = #LName AND
FName = #FName AND
MInit = #MInit
SET #RecordCount = ##ROWCOUNT
RETURN
Method/Code:
public static DataSet Confirmation()
{
SqlCommand cmdSQL = new SqlCommand("uspConfirmation", Connection);
cmdSQL.CommandType = CommandType.StoredProcedure;
cmdSQL.Parameters.Add(new SqlParameter("#RecordID", SqlDbType.VarChar, 36));
cmdSQL.Parameters["#RecordID"].Direction = ParameterDirection.Input;
cmdSQL.Parameters["#RecordID"].Value = RecordIDSession;
cmdSQL.Parameters.Add(new SqlParameter("#LName", SqlDbType.VarChar, 30));
cmdSQL.Parameters["#LName"].Direction = ParameterDirection.Input;
cmdSQL.Parameters["#LName"].Value = LNameSession;
cmdSQL.Parameters.Add(new SqlParameter("#FName", SqlDbType.VarChar, 30));
cmdSQL.Parameters["#FName"].Direction = ParameterDirection.Input;
cmdSQL.Parameters["#FName"].Value = FNameSession;
cmdSQL.Parameters.Add(new SqlParameter("#MInit", SqlDbType.Char, 1));
cmdSQL.Parameters["#MInit"].Direction = ParameterDirection.Input;
cmdSQL.Parameters["#MInit"].Value = MNameSession;
cmdSQL.Parameters.Add(new SqlParameter("#RecordCount", SqlDbType.Int));
cmdSQL.Parameters["#RecordCount"].Direction = ParameterDirection.Output;
... then a variable to hold the row count via an output variable ...
Int32 intRecCount = Convert.ToInt32(cmdSQL.Parameters["#RecordCount"].Value);
SqlDataAdapter da = new SqlDataAdapter(cmdSQL);
DataSet ds = new DataSet();
da.Fill(ds);
try {
Connection.Open();
cmdSQL.ExecuteNonQuery();
}
catch (Exception ex) {
dbMsg = ex.Message;
}
finally {
Connection.Close();
cmdSQL.Dispose();
cmdSQL.Parameters.Clear();
}
return ds;
}
You need to access the value of output parameter after executing the query not before. So move this line after execution of query, and before clearing parameters, like:
//VARIABLE TO HOLD ROW COUNT VIA OUTPUT VIARABLE
Int32 intRecCount = Convert.ToInt32(cmdSQL.Parameters["#RecordCount"].Value);
So your code for method would be:
public static DataSet Confirmation()
{
SqlCommand cmdSQL = new SqlCommand("uspConfirmation", Connection);
cmdSQL.CommandType = CommandType.StoredProcedure;
cmdSQL.Parameters.Add(new SqlParameter("#RecordID", SqlDbType.VarChar, 36));
cmdSQL.Parameters["#RecordID"].Direction = ParameterDirection.Input;
cmdSQL.Parameters["#RecordID"].Value = RecordIDSession;
cmdSQL.Parameters.Add(new SqlParameter("#LName", SqlDbType.VarChar, 30));
cmdSQL.Parameters["#LName"].Direction = ParameterDirection.Input;
cmdSQL.Parameters["#LName"].Value = LNameSession;
cmdSQL.Parameters.Add(new SqlParameter("#FName", SqlDbType.VarChar, 30));
cmdSQL.Parameters["#FName"].Direction = ParameterDirection.Input;
cmdSQL.Parameters["#FName"].Value = FNameSession;
cmdSQL.Parameters.Add(new SqlParameter("#MInit", SqlDbType.Char, 1));
cmdSQL.Parameters["#MInit"].Direction = ParameterDirection.Input;
cmdSQL.Parameters["#MInit"].Value = MNameSession;
cmdSQL.Parameters.Add(new SqlParameter("#RecordCount", SqlDbType.Int));
cmdSQL.Parameters["#RecordCount"].Direction = ParameterDirection.Output;
SqlDataAdapter da = new SqlDataAdapter(cmdSQL);
DataSet ds = new DataSet();
da.Fill(ds);
Int32 intRecCount = 0;
try
{
Connection.Open();
cmdSQL.ExecuteNonQuery();
//VARIABLE TO HOLD ROW COUNT VIA OUTPUT VIARABLE
intRecCount = Convert.ToInt32(cmdSQL.Parameters["#RecordCount"].Value);
}
catch (Exception ex)
{
dbMsg = ex.Message;
}
finally
{
Connection.Close();
cmdSQL.Dispose();
cmdSQL.Parameters.Clear();
}
return ds;
}