Согласно комментарию Ларну, вы выполняли запрос дважды. В этом случае вы должны использовать только версию ExecuteScalar () для извлечения последнего вставленного идентификатора для последующего использования
Я также хотел бы отметить, что целью проекта является один раз инициализировать коллекцию параметров, а затем повторно использовать ее много раз. раз, выполняя каждый раз. Вы также должны поместить using
операторы, чтобы сделать ваши команды, более похожими на это, и вы, вероятно, должны привыкнуть использовать SCOPE_IDENTITY () вместо @@ identity:
using(var con = new SqlConnection(...)){
con.Open();
string bal = txtBal.Text;
string sub = txtSub.Text;
string pay = textBox1.Text;
sql = "insert into sales(subtoal,pay,bal) values(@subtoal,@pay,@bal); select scope_identity();";
int lastinsertId = 0;
using(var cmd = new SqlCommand(sql, con){
cmd.Parameters.AddWithValue("@subtoal", sub);
cmd.Parameters.AddWithValue("@pay", pay);
cmd.Parameters.AddWithValue("@bal", bal);
lastinsertID = (int)cmd.ExecuteScalar();
}
string proddname = "";
int price = 0;
int qty = 0;
int tot = 0;
sql1 = "insert into sales_product(sales_id,prodname,price,qty,total) values(@sales_id,@prodname,@price,@qty,@total)";
using(var cmd1 = new SqlCommand(sql1, con)){
cmd1.Parameters.AddWithValue("@sales_id", lastinsertID);
cmd1.Parameters.AddWithValue("@prodname", proddname);
cmd1.Parameters.AddWithValue("@price", price);
cmd1.Parameters.AddWithValue("@qty", qty);
cmd1.Parameters.AddWithValue("@total", total);
for (int row = 0; row < dataGridView1.Rows.Count; row++)
{
proddname = dataGridView1.Rows[row].Cells[0].Value.ToString();
price = int.Parse(dataGridView1.Rows[row].Cells[1].Value.ToString());
qty = int.Parse(dataGridView1.Rows[row].Cells[2].Value.ToString());
int total = int.Parse(dataGridView1.Rows[row].Cells[3].Value.ToString());
cmd1 = new SqlCommand(sql1, con);
cmd1.Parameters["@sales_id"].Value = lastinsertID;
cmd1.Parameters["@prodname"].Value = proddname;
cmd1.Parameters["@price"].Value = price;
cmd1.Parameters["@qty"].Value = qty;
cmd1.Parameters["@total"].Value = total;
cmd1.ExecuteNonQuery();
}
} //end using sqlcommand
}//end using sqlconnection - it will close as a result
MessageBox.Show("Record Addddedddd");
И тогда я также хотелуказать, что ваша жизнь может стать намного проще, если вы используете Dapper. С помощью dapper код будет выглядеть примерно так:
using(var connection = new SqlConnection(...))
sql = "insert into sales(subtoal,pay,bal) values(@subtoal,@pay,@bal); select scope_identity();";
var lastInsertId = connection.Query<int>(sql, new {
subtoal = txtSub.Text,
pay = textBox1.Text,
bal = txtBal.Text
}
).Single();
foreach(...)
}
Он выполняет все переключение параметров для вас, выполняет запрос, управляет соединением, возвращает тип, приведенный к типу int и т. Д.
Также, если вашdatagridview основан на DataTable (а еще лучше - строго типизированном datatable), который вы можете использовать в своем foreach. Вот как будет выглядеть строго типизированная таблица:
using(...){
foreach(var ro in SalesProductTable){
sql = "insert into sales_product(sales_id,prodname,price,qty,total) values(@sales_id,@prodname,@price,@qty,@total)";
dapperConnection.Execute(sql, new { ro.sales_id, ro.prodname, ro.price, ro.qty, ro.total });
}
Да, вот и все;всего 4 строки кода, и это проще, если имена @param совпадают с именами столбцов в строго типизированной таблице.
Я думаю, что вы могли бы даже заставить Dapper также выполнять циклы, передавая данные, если строки имеют свойства, совпадающие с параметрами в запросе:
using(...){
sql = "insert into sales_product(sales_id,prodname,price,qty,total) values(@sales_id,@prodname,@price,@qty,@total)";
dapperConnection.Execute(sql, salesProductTable);
}
взгляните - http://dapper -tutorial.net