C# call stored MYSQL procedure with input parameter - c#

I'm calling stored procedure finish_record with 1 input parameter.
I read all related questions here for this topic but I didn't see mistake on my side...
But somewhere is it :-)
here procedure:
CREATE DEFINER=`root`#`localhost` PROCEDURE `finish_record`(
IN recordId INT
)
BEGIN
UPDATE bnirolovani.record r INNER JOIN(
select Sum(SumError) as Total, count(RollID) as Rolls, sum(Lenght) as Lenght, sum(ExtraMeter) as ExtraMeter from bnirolovani.roll where RecordID=recordId)
i on r.RecordID = recordId SET r.SumError = i.Total, r.SumReels=i.Rolls,r.SumProduced=i.Lenght, r.SumExtraMeter=ExtraMeter;
UPDATE record r
INNER JOIN
(SELECT
SUM(Lenght) AS Total
FROM
bnirolovani.roll
WHERE
RecordID = recordId AND Quality = 0) i ON r.RecordID = recordId
SET
r.QualityE = i.Total;
UPDATE record r
INNER JOIN
(SELECT
SUM(Lenght) AS Total
FROM
bnirolovani.roll
WHERE
RecordID = recordId AND Quality = 1) i ON r.RecordID = recordId
SET
r.QualityII = i.Total;
UPDATE record r
SET
DateProducedF = NOW()
WHERE
r.RecordID = recordID;
END
and here my C# code
private void FinishRecord(int recordID)
{
try
{
string con = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
using (MySqlConnection conection = new MySqlConnection(con))
{
using (MySqlCommand cmd = new MySqlCommand("finish_record", conection))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("recordId", MySqlDbType.Int32).Value=recordID;
conection.Open();
cmd.ExecuteNonQuery();
conection.Close();
}
}
}
catch (Exception ex)
{
throw;
}
Could someone help me where is mistake? I didn't see it :-(
THX

Solved
I replace C# code:
Add procedure call as simple CommandType=Command.Text instead of CommandType.Procedure
and works
private void FinishRecord(int recordID)
{
try
{
string con = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
using (MySqlConnection conection = new MySqlConnection(con))
{
using (MySqlCommand cmd = new MySqlCommand())
{
cmd.Connection = conection;
cmd.CommandType = CommandType.Text;
cmd.CommandText = String.Format("CALL finish_record({0})",recordID);
conection.Open();
cmd.ExecuteNonQuery();
conection.Close();
}
}
}
catch (Exception ex)
{
throw;
}
}

Related

Get an identity value in a controller for INSERT (Execute Insert command and return inserted Id in Sql)

Currently, I am using MVC on creating a project. Now I want to insert an Identity ID value into an INSERT statement.
In my controller:
string payment = #"INSERT INTO Payment(Payment_Method,Currency_Type,Total_Amount)
VALUES('{0}','{1}',{2})";
int pay = DBUtl.ExecSQL(payment, "Cash", currency,total);
if (pay == 1)
{
string pid = "SELECT TOP 1 Payment_id FROM Payment ORDER BY Payment_id DESC";
int paymentid = DBUtl.ExecSQL(pid);
if (cart.Count() != 0)
{
string order = #"INSERT INTO [Order](Order_Name,Order_Description,Order_Quantity,Payment_Id)
VALUES('{0}','{1}',{2},{3})";
Now, I want to the payment_id that already been inserted into the payment table which is the first statement and retrieve the payment_id and use it into the INSERT statement for the Order table
How can I achieve that?
Please Help
Thank you
Actually, DBUtil code consists of:
public static int ExecSQL(string sql, params object[] list)
{
List<String> escParams = new List<String>();
foreach (object o in list)
{
if (o == null)
escParams.Add("");
else
escParams.Add(EscQuote(o.ToString()));
}
DB_SQL = String.Format(sql, escParams.ToArray());
int rowsAffected = 0;
using (SqlConnection dbConn = new SqlConnection(DB_CONNECTION))
using (SqlCommand dbCmd = dbConn.CreateCommand())
{
try
{
dbConn.Open();
dbCmd.CommandText = DB_SQL;
rowsAffected = dbCmd.ExecuteNonQuery();
}
catch (System.Exception ex)
{
DB_Message = ex.Message;
rowsAffected = -1;
}
}
return rowsAffected;
}
And as you know ExecuteNonQuery denotes the numbers affecting the row
So, You can do as shown below:
FOR SQL SERVER 2005 and above
using (SqlConnection con=new SqlConnection(#"Your connectionString"))
{
using(SqlCommand cmd=new SqlCommand("INSERT INTO Payment(Payment_Method,Currency_Type,Total_Amount) output INSERTED.Payment_id VALUES(#Payment_Method,#Currency_Type,#Total_Amount)",con))
{
cmd.Parameters.AddWithValue("#Payment_Method", "Cash");
cmd.Parameters.AddWithValue("#Currency_Type", currency);
cmd.Parameters.AddWithValue("#Total_Amount", total);
con.Open();
int payment_id =Convert.ToInt32(cmd.ExecuteScalar());
if (con.State == System.Data.ConnectionState.Open)
con.Close();
return payment_id ;
}
}
also, you can change your query to:
"INSERT INTO Payment(Payment_Method,Currency_Type,Total_Amount) VALUES(#Payment_Method,#Currency_Type,#Total_Amount)"; SELECT SCOPE_IDENTITY()"
For now, I tried something like this:
public IActionResult SaveDetail(List<Cart_Has_Services> cart,double total,string currency)
{
string payment = #"INSERT INTO Payment(Payment_Method,Currency_Type,Total_Amount)
VALUES('{0}','{1}',{2});";
int pay = DBUtl.ExecSQL(payment, "Cash", currency,total);
if (pay == 1)
{
object pid = DBUtl.GetList("SELECT Payment_id FROM Payment");
int paymentid = Convert.ToInt32(pid);
if (cart.Count() != 0)
{
string order = #"INSERT INTO [Order](Order_Name,Order_Description,Order_Quantity,Payment_Id)
VALUES('{0}','{1}',{2},{3})";
foreach (var item in cart)
{
int ord = DBUtl.ExecSQL(order, item.Cart_Service, item.Additional_Notes, item.Quantity,paymentid);
As for now, the codes will run by inserting the values into the payment table. After that, I want to get the payment_id for my next insert which is the order table.
The method that I tried to get the payment_id does not work.

Is there a way to validate the connection string if the server is closed or down?

I have problem regarding inserting the loop process. So when the connection string determine that the server is down, the inserting process stop looping. My question, is there way to determine whether this connection string is down or not? I have research they answer is to make if condition sqlconn.State == ConnectionState.Open I will show you guys the sample error that I encounter.
string connetionString = null;
MySqlConnection cnn;
connetionString = "server=localhost;database=sample_db_xx;uid=root;pwd=;";
cnn = new MySqlConnection(connetionString);
try
{
var arpp_pro = new List<string>();
cnn.Open();
MySqlCommand command = new MySqlCommand("SELECT store_id,CONCAT(boh,'\\\\sqlexpress') as boh FROM db_cua.stores WHERE " +
"is_active = 1 AND boh != '' ", cnn);
using (MySqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine(reader[0].ToString());
arpp_pro.Add(reader[1].ToString());
}
}
cnn.Close();
foreach (var arpp_pro_data in arpp_pro)
{
string connetionString_SQL = #"Server=" + arpp_pro_data + " \sqlexpress;Database=Site5;User ID=sa;Password=dospos";
//#"Server=" + arpp_pro_data + ";Database=Site5;User ID=sa;Password=dospos";
var date_minus_one_day = DateTime.Today.AddDays(-1);
var formatted_date_minus_one_day = date_minus_one_day.ToString("yyyy-MM-dd");
var year = DateTime.Now.ToString("yyyy");
var month = DateTime.Now.ToString("MM");
var date = DateTime.Today.AddDays(-1);
var date_formatted = date.ToString("dd");
string get_sos_orders_details = #"SELECT
Convert(nvarchar(50),dbo.SOS_ORDERS.OrderId)+ '-'+ Convert(nvarchar(50),dbo.SOS_ORDERS.TransTime) + Convert(nvarchar(50),dbo.Sales.TransactionId)+ Convert(nvarchar(50),dbo.Sales.TotalDeptName) as result,
dbo.Sales.StoreId,
Convert(nvarchar(50),dbo.SOS_ORDERS.TransTime) as TransTime,
dbo.Transactions.OperatorName as Cashier,
dbo.Sales.TotalDeptName as Transaction_Type,
dbo.Sales.TransactionId,
(dbo.SOS_ORDERS.DTOT + dbo.SOS_ORDERS.ASSM) as Cashier_Time,
(dbo.SOS_ORDERS.KIT) as Preparation_Time,
(dbo.SOS_ORDERS.KIT + dbo.SOS_ORDERS.DTOT + dbo.SOS_ORDERS.ASSM) as Total_Time
FROM dbo.SOS_ORDERS INNER JOIN
dbo.Sales ON dbo.SOS_ORDERS.OrderId = dbo.Sales.StoredOrderIndex INNER JOIN
dbo.Transactions ON dbo.Sales.Sequence = dbo.Transactions.Sequence
where dbo.Sales.businessdate= #date_minus_one_day
OR(DATEPART(yy, dbo.SOS_ORDERS.TransTime) = #year
AND DATEPART(mm, dbo.SOS_ORDERS.TransTime) = #month
AND DATEPART(dd, dbo.SOS_ORDERS.TransTime) = #date_today )
AND(dbo.Sales.TotalDeptName in ('01 SALLE MANGER', '02 EMPORTER')
or dbo.Sales.TotalDeptName in ('01 DINE IN', '02 TAKE OUT'))
GROUP BY dbo.SOS_ORDERS.OrderId, dbo.Sales.StoreId, dbo.SOS_ORDERS.TransTime, dbo.SOS_ORDERS.DTOT, dbo.SOS_ORDERS.LINE, dbo.SOS_ORDERS.WIND, dbo.SOS_ORDERS.SERV, dbo.SOS_ORDERS.HOLD,
dbo.SOS_ORDERS.TOTL, dbo.SOS_ORDERS.ASSM, dbo.SOS_ORDERS.CASH, dbo.SOS_ORDERS.FTOT, dbo.SOS_ORDERS.PAY, dbo.SOS_ORDERS.KIT, dbo.Sales.TransactionId,
dbo.Transactions.OperatorName, dbo.Sales.TotalDeptName order by dbo.SOS_ORDERS.TransTime DESC";
using (SqlConnection sqlconn = new SqlConnection(connetionString_SQL))
{
sqlconn.Open();
if (sqlconn.State == ConnectionState.Open)
{
SqlCommand cmd = new SqlCommand(get_sos_orders_details, sqlconn);
cmd.Parameters.AddWithValue("#date_minus_one_day", formatted_date_minus_one_day);
cmd.Parameters.AddWithValue("#year", year);
cmd.Parameters.AddWithValue("#month", month);
cmd.Parameters.AddWithValue("#date_today", date_formatted);
SqlDataReader rs = cmd.ExecuteReader();
while (rs.Read())
{
// access your record colums by using reader
Console.WriteLine(rs["StoreId"]);
cnn.Open();
MySqlCommand comm = cnn.CreateCommand();
comm.CommandText = #"INSERT INTO master_data.so_v2 (StoreId,TransTime,Cashier,Transaction_Type,TransactionId,Cashier_Time,Preparation_Time)
VALUES(#Storeid, #TransTime, #Cashier, #Transaction_Type, #TransactionId, #Cashier_Time, #Preparation_Time)";
comm.Parameters.AddWithValue("#Storeid", rs["StoreId"]);
comm.Parameters.AddWithValue("#TransTime", rs["TransTime"]);
comm.Parameters.AddWithValue("#Cashier", rs["Cashier"]);
comm.Parameters.AddWithValue("#Transaction_Type", rs["Transaction_Type"]);
comm.Parameters.AddWithValue("#TransactionId", rs["TransactionId"]);
comm.Parameters.AddWithValue("#Cashier_Time", rs["Cashier_Time"]);
comm.Parameters.AddWithValue("#Preparation_Time", rs["Preparation_Time"]);
comm.ExecuteNonQuery();
cnn.Close();
}
}
sqlconn.Close();
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Thank you.
I suppose if all you wanted was a way to test and make sure a connection string is valid and that you can connect to the server and to the database, you could use a method like this:
public bool IsConnectionStringValid(string cs)
{
try
{
using (MySqlConnection conn = new MySqlConnection(cs))
{
conn.Open();
return true;
}
}
catch
{
return false;
}
}
Although I have to admit, in all my years of developing in C#, I've never used anything like this. Normally, as people have said in the comments, you already know before runtime that your connection string is valid and working.

How to pass multiple listbox items (characters such as A,S,I,SIP,SIPA etc...)to parameterized SQL query using IN?

I have found numerous posts on this but I haven't been able to make any
of them work. The code below is the closest I have come to
making it work. I read out the values for the ddlSIPA listbox below and
the result looks correct but it seems SQL server isn't handling the
IN statement for the listbox items.
public void LoadChecklist(Object sender, EventArgs e)
{
System.Data.DataTable SearchResultsTable = new System.Data.DataTable();
SqlCommand cmd = new SqlCommand("sp_get_QUADRA_CHECKLIST", conn);
cmd.CommandType = CommandType.StoredProcedure;
//create sql adapter by passing command object
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
SearchResultsTable.Clear();
string strYourIDs = "";
int[] yourSelectedIndexes = ddlSIPA.GetSelectedIndices();
for (int i = yourSelectedIndexes.Length - 1; i >= 0; i--)
{
strYourIDs += "'" + ddlSIPA.Items[yourSelectedIndexes[i]].Value + "',";
}
if (strYourIDs != "")
strYourIDs = strYourIDs.TrimEnd(",".ToCharArray());
try
{
cmd.Parameters.AddWithValue("#SIPA", strYourIDs);
Response.Write(strYourIDs);
cmd.Parameters.AddWithValue("#AP_DEV", CbAPDev.Checked);
cmd.Parameters.AddWithValue("#PROD_DEV", cbProdDev.Checked);
cmd.Parameters.AddWithValue("#ROTYPE", ddlROTYPE.SelectedItem.Value);
adapter.Fill(SearchResultsTable);
if (SearchResultsTable.Rows.Count > 0)
{
//SearchResultsTable.ToString();
GV1.DataSource = SearchResultsTable;
GV1.DataBind();
}
else if (SearchResultsTable.Rows.Count == 0)
{
//Response.Write("No records found!");
ScriptManager.RegisterStartupScript(this, GetType(), "showalert", "alert('No records found!');", true);
GV1.DataBind();
}
}
catch (System.Data.SqlClient.SqlException ex)
{
Response.Write(ex);
}
finally
{
conn.Close();
}
}
SQL Query:
USE [VISIBILITY_BOARD]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO
ALTER PROCEDURE [dbo].[sp_get_QUADRA_CHECKLIST] (
#AP_DEV bit ''
,#PROD_DEV bit = ''
,#ROTYPE nvarchar(255) = ''
,#SIPA nvarchar(255) = '') AS
--,#RO nvarchar(255) = '') AS
SELECT h.QUES_ANSWER
, h.COMMENTS
, cl.RO_TYPE
, cl.RO
, cl.QUES_ID
, cl.DFQRO AS QDRO
, cl.QUADRA_QUES
FROM Tbl_QUADRA_CL cl
LEFT JOIN TBL_QUADRA_ASSMNT_HIST h
ON cl.QUES_ID = h.QUES_ID
WHERE (cl.RO_TYPE = #ROTYPE OR #ROTYPE IS NULL)
AND (cl.SIPA IN (#SIPA) OR #SIPA IS NULL)
AND (cl.AP_DEV = #AP_DEV OR #AP_DEV IS NULL)
AND (cl.PROD_DEV = #PROD_DEV or #PROD_DEV IS NULL)
GROUP BY h.QUES_ANSWER
, h.COMMENTS
, cl.RO_TYPE
, cl.RO
, cl.QUES_ID
, cl.DFQRO
, cl.QUADRA_QUES
SET QUOTED_IDENTIFIER On
GO
Here is your problem: AND (cl.SIPA IN (#SIPA) OR #SIPA IS NULL)
You are making a very common mistake - The IN operator expects a list of values separated by a comma, but you are giving it a single value that happens to contain a comma-separated list.
Since you are using c# and sql-server, I would advise to use a table valued parameter instead.
Please note that there are also some other problems in your code:
Using a class level SQLConnection - That's a mistake. A correct use of SQLConnection would be as a local variable inside a using statement.
Using instances of classes that implements the IDisposable interface and not disposing them - SQLCommand and SQLDataAdapter in your case.
Using AddWithValue - Read Can we stop using AddWithValue() already? for details.
A better c# code would look more like this:
public void LoadChecklist(Object sender, EventArgs e)
{
var SearchResultsTable = new DataTable();
using (var con = new SqlConnection("<ConnectionStringGoesHere>"))
{
using (var cmd = new SqlCommand("sp_get_QUADRA_CHECKLIST", con))
{
cmd.CommandType = CommandType.StoredProcedure;
using(var adapter = new SqlDataAdapter(cmd))
{
using(var dtSIPA = new DataTable())
{
dtSIPA.Columns.Add("Id", typeof(int)); -- assuming you are looking for a list of int values
int[] yourSelectedIndexes = ddlSIPA.GetSelectedIndices();
for (int i = yourSelectedIndexes.Length - 1; i >= 0; i--)
{
dtSIPA.Rows.Add(ddlSIPA.Items[yourSelectedIndexes[i]].Value);
}
cmd.Parameters.Add("#AP_DEV", SqlDbType.Bit).Value = CbAPDev.Checked;
cmd.Parameters.Add("#PROD_DEV", SqlDbType.Bit).Value = cbProdDev.Checked;
cmd.Parameters.Add("#ROTYPE", SqlDbType.NVarChar, 255).Value = ddlROTYPE.SelectedItem.Value;
cmd.Parameters.Add("#SIPA", SqlDbType.Structured).Value = dtSIPA;
}
try
{
adapter.Fill(SearchResultsTable);
}
catch (System.Data.SqlClient.SqlException ex)
{
Response.Write(ex);
}
}
}
}
}
As for your stored procedure, you need to create a user defined table type for the #SIPA parameter:
CREATE TYPE SIPA AS TABLE
(
Id int
)
and change the condition to AND (cl.SIPA IN (SELECT Id FROM #SIPA) OR (SELECT COUNT(*) FROM #SIPA) = 0)

What is the return value of ExecuteNonQuery statement?

I have written a program to verify username and password using 3 tier architecture in Visual Studio 10. In the DAL, ExecuteNonQuery statement returns '-1'. But I want it to return '1' if username and password are correct or '0'if not correct.
Code snipped for DAL:
public class LoginDataAccess
{
SqlConnection con;
string constr = ConfigurationManager.ConnectionStrings["localhostakash"].ToString();
public int LoginData(LoginEntity elOj)
{
try
{
con = new SqlConnection(constr);
int result;
if(ConnectionState.Closed==con.State)
con.Open();
SqlCommand cmd = new SqlCommand("uspuserlogin", con);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Username", elOj.Username);
cmd.Parameters.AddWithValue("#Password", elOj.Password);
result = Convert.ToInt32(cmd.ExecuteNonQuery());
return result;
}
catch (Exception ex)
{
throw ex;
}
finally
{
con.Close();
}
}
}
Code snippet for BLL:
public class LoginLogic
{
LoginDataAccess lda = new LoginDataAccess();
public int userValidate(LoginEntity le)
{
int result = 0;
try
{
result = Convert.ToInt32(lda.LoginData(le));
}
catch (Exception ex)
{
//response.write(ex.Message);
}
return result;
}
}
Code snippet for button function:
protected void Button1_Click(object sender, EventArgs e)
{
LoginLogic ll = new LoginLogic();
LoginEntity le = new LoginEntity();
int v;
le.Username = TextBox1.Text;
le.Password = TextBox2.Text;
v = Convert.ToInt32(ll.userValidate(le));
if (v == 1)
{
Label1.Text = "LOGGED IN SUCCESSFULLY!";
}
else
{
Label1.Text = "TRY AGAIN...";
}
}
Here is the documentation:
For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. When a trigger exists on a table being inserted or updated, the return value includes the number of rows affected by both the insert or update operation and the number of rows affected by the trigger or triggers. For all other types of statements, the return value is -1. If a rollback occurs, the return value is also -1.
Read more here: https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executenonquery.aspx
You are calling a stored procedure "uspuserlogin". That's why ExecuteNonQuery returns -1.
You can return value as row if you need to know result of operation.
ALTER PROCEDURE [dbo].[uspuserlogin]
#username nvarchar(255),
#password nvarchar(255)
AS
BEGIN
SELECT COUNT(*) AS Found
FROM [Users]
WHERE [Username] = #username AND [Password] = #password
END
In code:
var obj = cmd.ExecuteScalar();
return (int)obj;
// Somewhere in code
if (loginDataAccess.LoginData(loginEntity) == 1)
// Authorize
Of course, you can transform it to bool for your convenience:
public bool LoginData(LoginEntity elOj)
{
try
{
con = new SqlConnection(constr);
int result;
if(ConnectionState.Closed==con.State)
con.Open();
SqlCommand cmd = new SqlCommand("uspuserlogin", con);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Username", elOj.Username);
cmd.Parameters.AddWithValue("#Password", elOj.Password);
var obj = cmd.ExecuteScalar();
return ((int)obj > 0);
}
catch (Exception ex)
{
throw ex;
}
finally
{
con.Close();
}
}

DbDataReader returns null

I created a stored procedure to get 1 row out of a table.
spGetDepartment
#ID int
AS
BEGIN
SELECT [ID],[Name],[Description]
FROM tblDepartments
WHERE [ID] = #ID
END
When stored procedure is tested in SQL I get the desired result.
When I try to call the stored procedure from code (C#) and debug the page I can see the reader gets populated correctly but when trying to read it, it changes to null value.
Here is the code calling the stored procedure.
public static Department GetDepartment(string ID)
{
Department Dept = new Department();
DbCommand comm = DataAccess.CreateCommand();
try
{
comm.CommandText = "spGetDepartment";
// create a new parameter
DbParameter _ID = comm.CreateParameter();
_ID.ParameterName = "#ID";
_ID.Value = ID;
_ID.DbType = DbType.Int32;
comm.Parameters.Add(_ID);
comm.Connection.Open();
DbDataReader rdr = comm.ExecuteReader();
while (rdr.Read())
{
Dept.DepartmentID = Convert.ToInt32(rdr["ID"].ToString());
Dept.DepartmentName = rdr["Name"].ToString();
Dept.Description = rdr["Description"].ToString();
}
rdr.Close();
}
catch (Exception ex)
{
Utilities.LogError(ex);
}
finally
{
comm.Dispose();
comm.Connection.Close();
}
return Dept;
}
Try this:
SqlDataReader rdr = comm.ExecuteReader();
if (rdr.HasRows)
{
reader.Read();
Dept.DepartmentID = Convert.ToInt32(rdr["ID"].ToString());
Dept.DepartmentName = rdr["Name"].ToString();
Dept.Description = rdr["Description"].ToString();
reader.Close();
}
else
{ //No data
}

Categories