SQL Server stored procedure insert query - c#

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.

Related

C# return double value from stored procedure

I want to return a double value from a stored procedure so I can call it from a form and multiplication its value in the value of the text box.
My stored procedure looks like this:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Get_Weight]
#ID INT,
#Weight FLOAT OUTPUT
AS
SELECT #Weight = [Weight]
FROM [Item]
WHERE ID_Item = #ID
This is my data access layer class:
class DataAccessLayer
{
SqlConnection sqlconnection;
public DataAccessLayer()
{
PL.FRM_LOGIN frm = new PL.FRM_LOGIN();
sqlconnection = new SqlConnection("Server='"+System.Environment.MachineName+"';DataBase='"+frm.txtDataBase.Text+"';Integrated Security=true");
}
// Method to open the connection
public void Open()
{
if(sqlconnection.State != ConnectionState.Open)
{
sqlconnection.Open();
}
}
// Method to close the connection
public void Close()
{
if(sqlconnection.State == ConnectionState.Open)
{
sqlconnection.Close();
}
}
// Method to read data from database
public DataTable SelectData(string stored_procedure, SqlParameter[] param)
{
SqlCommand sqlcmd = new SqlCommand();
sqlcmd.CommandType = CommandType.StoredProcedure;
sqlcmd.CommandText = stored_procedure;
sqlcmd.Connection = sqlconnection;
if (param != null)
{
sqlcmd.Parameters.AddRange(param);
}
SqlDataAdapter da = new SqlDataAdapter(sqlcmd);
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}
// Method to insert, update and delete data from database
public void ExecuteCommand(string stored_procedure, SqlParameter[] param)
{
SqlCommand sqlcmd = new SqlCommand();
sqlcmd.CommandType = CommandType.StoredProcedure;
sqlcmd.CommandText = stored_procedure;
sqlcmd.Connection = sqlconnection;
if (param != null)
{
sqlcmd.Parameters.AddRange(param);
}
sqlcmd.ExecuteNonQuery();
}
}
I want to create a class in the business layer with a method that can return the value - for example
public void Get_Weight(int ID, double UWeight)
{
DAL.DataAccessLayer DAL = new DAL.DataAccessLayer();
DAL.Open();
SqlParameter[] param = new SqlParameter[2];
param[0] = new SqlParameter("#ID", SqlDbType.Int);
param[0].Value = ID;
param[1] = new SqlParameter("#Weight", SqlDbType.Float);
param[1].Value = UWeight;
param[1].Direction = ParameterDirection.Output;
DAL.ExecuteCommand("Get_Weight", param);
DAL.Close();
}
And after that, I call that method from the form
void CalculateWeight()
{
if (txtLength.Text != string.Empty && cmbName.Text != null)
{
txtWeight.Text = (Convert.ToInt32(txtLength.Text) *(//the code)).ToString();
}
}
Please help me
If this were a code review I would have a number of issues with your approach to a Data Access Layer, but to solve your immediate problem I would suggest you change your Get_Weight method to return a double and not take a UWeight argument. Since your OUTPUT parameter is only set and not also used as input, you can give it a value of DBNull.Value. Lastly, it looks like you might have a typo in your procedure, is the column name really "Wight"?
public double Get_Weight(int ID)
{
DAL.DataAccessLayer DAL = new DAL.DataAccessLayer();
DAL.Open();
SqlParameter[] param = new SqlParameter[2];
param[0] = new SqlParameter("#ID", SqlDbType.Int);
param[0].Value = ID;
param[1] = new SqlParameter("#Weight", SqlDbType.Float);
param[1].Value = DBNull.Value;
param[1].Direction = ParameterDirection.Output;
DAL.ExcuteCommande("Get_Weight", param);
DAL.Close();
double weight = 0.0;
if(double.TryParse(param[1]?.Value?.ToString(), out weight)
{
return weight;
}
else
{
throw new ArgumentException("No Item found for given ID");
}
}
Use ExecuteScalar to get a value from a stored procedure
public double ExcuteCommande(string stored_procedure,SqlParameter[] param)
{
SqlCommand sqlcmd = new SqlCommand();
sqlcmd.CommandType = CommandType.StoredProcedure;
sqlcmd.CommandText = stored_procedure;
sqlcmd.Connection = sqlconnection;
if (param!=null)
{
sqlcmd.Parameters.AddRange(param);
}
var back=sqlcmd.ExecuteScalar();
double result;
double.TryParse(back.ToString(), out result);
return result;
}

Replacement for SQL query with stored procedure

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.

DataTable Is Empty

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);
}

How can I get SQL Server stored procedure return value in c#?

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...

executenonquery not working in for loop

In database:
Alter Procedure Update_MaterialTransactionsto2ForWithdrawal
#materialName varchar(50),
#staffNumber varchar(10),
#description varchar(50),
#transactionID int
As
Begin
Update Table_MaterialTransactions
set Status=2
where StaffNumber = #staffNumber
and CrossSection = #description
and SubSubCategory = #materialName
and Status = 1
and TransactionID = #transactionID
End
In data access layer:
public static void UpdateMaterial(string staffNumber,string materialName,string description,int transaction)
{
SqlConnection connection = new SqlConnection(ConnectDatabase.ReturnConnectionString());
//I am passing connection string as the parameter
try
{
connection.Open();
SqlCommand cmd = new SqlCommand("Update_MaterialTransactionsto2ForWithdrawal", connection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Clear();
cmd.Parameters.Add("#materialName", SqlDbType.Varchar, 50).Value = materialName;
cmd.Parameters.Add("#staffNumber", SqlDbType.Varchar, 50).Value = staffNumber;
cmd.Parameters.Add("#description", SqlDbType.Varchar, 50).Value = description;
cmd.Parameters.Add("#transactionID", SqlDbTypeInt).Value = transactionID;
int i = cmd.ExecuteNonQuery();
connection.Close();
}
catch(Exception ex)
{
connection.Close();
}
On the client side:
void btnSubmit_Click(Object sender,EventArgs e)
{
int j=0,k=0;
for(int i=0;i<transactions.Count;i++)
{
string id = "ctl00$ContentPlaceHolder1$" + i.ToString();
CheckBox chk=(CheckBox)Page.FindControl(id);
if(chk.Checked == true)
{
Objects.UpdateMaterial(staffNumbers[i].ToString(), materials[i].ToString(), descriptions[i].ToString(), Convert.ToInt32(transactions[i]));
j++;
}
else
{
Objects.DeleteTheSelectedRowOfMaterialTransaction(staffNumbers[i].ToString(), materials[i].ToString(), descriptions[i].ToString(), Convert.ToInt32(transactions[i]));
k++;
}
}
I have check boxes in the table and when the user checks the check boxes and clicks submit, the boxes which are checked will update the database.
But the cmd.ExecuteNonQuery() is not executing and it is returning 0 rows. It is not throwing any error. But if I do this manually in the database, the stored procedure is working fine.
Kindly tell me where I am going wrong.
try adding last line in procedure
Return ##Rowcount

Categories