I'm trying to add data to my master/detail table by using a stored procedure.
I tried this:
private void ekle()
{
MySqlCommand cmd = new MySqlCommand("invinputfrompo", bag);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("?trnotes", MySqlDbType.Text).Value = tb1.Text;
for (int i = 0; i <= dg1.Rows.Count - 1; i++)
{
if (Convert.ToBoolean(dg1.Rows[i].Cells[0].Value) == true)
{
cmd.Parameters.Add("?docno", MySqlDbType.VarChar).Value = dg1.Rows[i].Cells[9].Value.ToString();
cmd.Parameters.Add("?idpodetails", MySqlDbType.Int32).Value = Convert.ToInt32(dg1.Rows[i].Cells[5].Value.ToString());
cmd.Parameters.Add("?idmat", MySqlDbType.Int32).Value = Convert.ToInt32(dg1.Rows[i].Cells[6].Value.ToString());
cmd.Parameters.Add("?sn", MySqlDbType.VarChar).Value = dg1.Rows[i].Cells[2].Value;
cmd.Parameters.Add("?qty", MySqlDbType.Decimal).Value = Convert.ToDecimal(dg1.Rows[i].Cells[1].Value);
//if (dg1.CurrentRow.Cells[4].Value.ToString() == "") { cmd.Parameters.Add("?shelflife", MySqlDbType.Date).Value = DBNull.Value; }
//else { cmd.Parameters.Add("?shelflife", MySqlDbType.Date).Value = dg1.CurrentRow.Cells[4].Value.ToString(); }
cmd.Parameters.Add("?shelflife", MySqlDbType.VarChar).Value = dg1.Rows[i].Cells[4].Value;
}
}
cmd.Connection = bag;
cmd.ExecuteNonQuery();
}
Only the first parameter "trnotes" will be added to the master table, other parameters will be added to the detail table.
I made loop like this but the way is not successful. it says you already defined "docno" (the first parameter in detail table)
Could you help for the data entry?
When your if statement runs for the second time, it tries to add docno to the list of parameters that was created on the first iteration. As docno was added in that first iteration, it already exists.
There are a couple of ways you could get around this:
Execute your stored procedure for each row. The downside is that you
have the overhead of additional DB calls.
Use User-Defined Table Types. You would build up your table in C#
and then pass that as a parameter to your stored procedure to
insert into your table.
Related
I am fetching a column from database of char(2) data type.
On an Event, I am changing the char data type to int and incrementing it by 1, with this code:
int i = 0;
using (SqlConnection sqlCon = new SqlConnection(Login.connectionString))
{
string commandString = "SELECT MAX(CAST(Category_Code as INT)) FROM Category;";
SqlCommand sqlCmd = new SqlCommand(commandString, sqlCon);
sqlCon.Open();
SqlDataReader dr = sqlCmd.ExecuteReader();
while (dr.Read())
{
i = 1;
if (dr[0] == null)
{
Ctgry_CtgryCodeCb.Text = "1";
}
else
{
int cat_next_code = int.Parse(dr[0].ToString());
Ctgry_CtgryCodeCb.Text = (cat_next_code + 1).ToString();
}
}
}
It is working properly but not for the first time (doesn't add 1 to empty or 0) as column is empty.It shows some error that it is not is correct format to convert. I also set the default value of the column to 0, but it shows ((0)) as default value.
Any help would be appreciated.
If you are using this code to increment primary key value of the database table, you shouldn't be doing this way. You should be using IDENTITY column feature available in the database.
Since you have not explained why you are not using IDENTITY column, looks like this code is for some other purpose.
As per your code you are getting Maximum value of some column from the database and incrementing it by one in the code.
When the table in the database is empty you not get anything is the reader. So While loop will not be executed at all. So even if you are checking for NullOrEmpty inside the while loop, it will never get executed.
Also you don't need to use SqlDataReader here. Since you are returning only one single value from the query you can use ExecuteScalar method of SqlCommand and get that value. It will be simpler.
var codeFromDb = sqlCmd.ExecuteScalar();
var cat_next_code = 0;
if(!(codeFromDb is DBNull))
{
cat_next_code = Convert.ToInt32(codeFromDb);
}
Ctgry_CtgryCodeCb.Text = (cat_next_code + 1).ToString();
My strong recommendation is to use IDENTITY column instead of doing all this code.
This will help you resolve your current issue.
SqlDataReader is overkill in this case and I don't like to answer for the wrong approach but since you insist consider following.
SqlDataReader dr = sqlCmd.ExecuteReader();
int cat_next_code = 0;
if(dr.Read()) // while is not needed here. There will be only one row in the reader as per the query.
{
i = 1;
if(!dr.IsDBNull(0))
{
cat_next_code = int.Parse(dr[0].ToString());
}
}
Ctgry_CtgryCodeCb.Text = (cat_next_code + 1).ToString();
I'm trying to insert all the data from 3 list-boxes to a table in the database i don't know if i'm doing well , this is the code i used
private void Order()
{
using (SqlConnection connection = new SqlConnection(connectionString1))
{
String query = "INSERT INTO Tbl_order (OrderName,Quantity,Price,Serves_way,Date) VALUES (#OrderName,#Quantity, #Price,'"+servers+"','" + time1.ToString(format1)+"' )";
using (SqlCommand command = new SqlCommand(query, connection))
{
connection.Open();
for (int i = 0; i < lst_OrderName.Items.Count; i++)
{
string OrderName = lst_OrderName.GetItemText(lst_OrderName.GetSelected(i));
command.Parameters.AddWithValue("#OrderName", lst_OrderName.GetItemText(lst_OrderName.GetSelected(i)));
command.Parameters.AddWithValue("#Quantity", lst_QTY.GetItemText(lst_QTY.GetSelected(i)));
command.Parameters.AddWithValue("#Price", lst_Price2.GetItemText(lst_Price2.GetSelected(i)));
command.Parameters.Add("#OrderName", SqlDbType.NVarChar);
command.Parameters.Add("#Quantity", SqlDbType.Int);
command.Parameters.Add("#Price", SqlDbType.Money);
command.Parameters.Add("#OrderName", SqlDbType.NVarChar).Value = OrderName;
command.Parameters.Add("#Quantity", SqlDbType.Int).Value = Convert.ToInt32(lst_QTY.GetSelected(i));
command.Parameters.Add("#Price", SqlDbType.Money).Value = Convert.ToDouble(lst_Price2.GetSelected(i));
}
// command.Parameters.AddWithValue("#OrderName", lst_OrderName.GetItemText(lst_OrderName.SelectedItem));
//command.Parameters.AddWithValue("#Quantity", lst_QTY.GetItemText(lst_QTY.SelectedItem));
//command.Parameters.AddWithValue("#Price", lst_Price2.GetItemText(lst_Price2.SelectedItem));
int result = command.ExecuteNonQuery();
// Check Error
if (result < 0)
Console.WriteLine("Error inserting data into Database!");
}
}
}
and i have a problem which is says
An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll
Additional information: The variable name '#OrderName' has already been declared. Variable names must be unique within a query batch or stored procedure.
this is the pic of the three list-boxes [![enter image description here][1]][1]
What is wrong in code what did i miss?
I want the data to be inserted in the database for each row like how does it look like in the pic .
You're trying to re-add the same parameters multiple times in a loop before ever executing the query. Even in a single iteration of the loop, you try to add every parameter three times. The error is telling you that you can only add the same parameter once.
Move the entire lifespan of the query to inside the loop. Something like this:
connection.Open();
for (int i = 0; i < lst_OrderName.Items.Count; i++)
{
using (SqlCommand command = new SqlCommand(query, connection))
{
command.Parameters.Add("#OrderName", SqlDbType.NVarChar).Value = OrderName;
command.Parameters.Add("#Quantity", SqlDbType.Int).Value = Convert.ToInt32(lst_QTY.GetSelected(i));
command.Parameters.Add("#Price", SqlDbType.Money).Value = Convert.ToDouble(lst_Price2.GetSelected(i));
command.ExecuteNonQuery();
}
}
This would also be a good time to learn about using transactions with a database. That way you can wrap all of these inserts in a single transaction and commit or rollback as needed.
EDIT: I am not able to format my code below, if any one can fix it.
I am new to sql queries and still learning.
Table Name: CommissionSetupTable.
I want to display #Paisa if gross_amount is between the range of #FromRate and #ToRate
Below is my code:
string paisa;
private void load_commission_setup()
{
SqlCeConnection conn = null;
SqlCeCommand cmd = null;
SqlCeDataReader rdr = null;
try
{
conn =
new SqlCeConnection(
#"Data Source=|DataDirectory|\Database.sdf;Persist Security Info=False");
conn.Open();
int rowindex = purchaseBillTableDataGridView.Rows.Count - 1;
gross_amount = double.Parse(purchaseBillTableDataGridView[10, rowindex].Value.ToString());
// Gross Amount is between the ranges of FromRate and ToRate.
cmd = new SqlCeCommand("SELECT Paisa FROM CommissionSetupTable WHERE='" + gross_amount.ToString() + "' BETWEEN #FromRate AND #ToRate;", conn);
rdr = cmd.ExecuteReader();
if (rdr == null)
{
}
else
{
while (rdr.Read())
{
paisa = rdr["Paisa"].ToString();
}
rdr.Close();
cmd.Dispose();
}
}
finally
{
conn.Close();
int rowindex = purchaseBillTableDataGridView.Rows.Count - 1;
purchaseBillTableDataGridView[11, rowindex].Value = paisa;
}
}
The correct syntax to use here is the following
cmd = new SqlCeCommand(#"SELECT Paisa FROM CommissionSetupTable
WHERE #gross BETWEEN FromRate AND ToRate;", conn);
Notice that the two field names should not be prefixed with #, otherwise they will be considered parameters placeholders.
And now, before executing the command, add the parameter for the #gross placeholder
cmd.Parameters.Add("#gross", SqlDbType.Decimal).Value = gross_amount;
I don't know what is the exact datatype of the columns FromRate and EndRate, but
note that you should use the correct datatype for your parameter. Do not pass a string and expect the database engine do the conversion for you. (or worse concatenate your value to the rest of the sql using ToString()). This is always wrong also if sometime the database engine could understand your values.
EDIT
Also, following your comments below, it appears that this line is wrong
int rowindex = purchaseBillTableDataGridView.Rows.Count - 1;
If your DataGridView has the property AllowUserToAddRow set to True then you want to use
int rowindex = purchaseBillTableDataGridView.Rows.Count - 2;
because the first line points to the empty row added to the DataGridView for inserting a new record.
There are so many questions on SO on this exception. But none of them are useful to me.
Here is my Stored Procedure :
CREATE PROCEDURE HolidayStandardMappingInsert
#HolidayID bigint,
#StandatdID smallint
AS
BEGIN
INSERT INTO HolidayStandardMapping VALUES(#HolidayID,#StandatdID)
END
GO
And here is my Code:
int StdId = 0;
SqlCommand cmdS = new SqlCommand("HolidayStandardMappingInsert", conn);
cmdS.CommandType = CommandType.StoredProcedure;
for (int i = 0; i < cblStandard.Items.Count; i++)
{
if (cblStandard.Items[i].Selected == true)
{
if (StdId == 0)
StdId = Convert.ToInt32(cblStandard.Items[i].Value);
else
StdId = Convert.ToInt32(cblStandard.Items[i].Value);
cmdS.Parameters.AddWithValue("#HolidayID", NewRecordID);
cmdS.Parameters.AddWithValue("#StandatdID", StdId);
if (conn.State == ConnectionState.Open)
{
conn.Close();
}
conn.Open();
int res = cmdS.ExecuteNonQuery();
if (res > 0)
{
}
}
}
Tell me what is missing?
You are using same SqlCommnad object for multiple insertions so previously added parameters are also present.
So either create a new SqlCommnad object inside loop or clear prevoius parameters.
This is how you can Clear Previously added parameters.
cmdS.Parameters.Clear();
You are adding parameters in a loop.
So after second iteration, your command has 4 parameters.
Each time You are adding cmdS.Parameters.AddWithValue in a loop. So after the first iteration, it has already 2 parameters.
You need to clear the command parameters by cmdS.Parameters.Clear() before entering the loop.
Here is my code in C#:
float r_discountValue = 0;
SqlConnection con = Constant.GetConnection();
SqlCommand cmd = new SqlCommand("Coupon_GetDiscountFromValidCouponCode", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#PKCouponCode", SqlDbType.VarChar);
cmd.Parameters["#PKCouponCode"].Value = "DIS_77";
try
{
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
if(reader.Read()){
r_discountValue = float.Parse(reader[0].ToString());
}
reader.Close();
}
catch(Exception exception)
{
throw exception;
}
finally{
con.Close();
}
return r_discountValue;
The stored procedure:
ALTER PROCEDURE [dbo].[Coupon_GetDiscountFromValidCouponCode]
#PKCouponCode varchar(50)
AS
SELECT *
FROM Coupon
WHERE CouponCode = #PKCouponCode AND Valid = 1
Here is how the DB looks like:
I encounter an error
Input string was not in a correct format
I don't know what's thing is going wrong, any ideas?
If you want the discount value, then you should return only the discount from the SP (since it is named GetDiscountfrom...)
SELECT CouponDiscount FROM Coupon WHERE CouponCode = #PKCouponCode AND Valid = 1
This will make it a one-column resultset, which matches the access reader[0] from C#.
The other option is of course to change the C# side to read the second item (index 1) or reference the column by name, e.g.
r_discountValue = float.Parse(reader[1].ToString());
r_discountValue = float.Parse(reader["CouponDiscount"].ToString());
You would have got Input string was not in a correct format. because it was reading "DIS_77" which float.parse cannot process.
You are using first column i.e.CouponCode for fetching discount. instead of that you need to use second column ie. couponDiscount
So try something like this
r_discountValue = float.Parse(reader["CouponDiscount"].ToString());