Reputation: 3575
Hello I'm trying to do following
I thought then T-SQL would be way to achieve that because when something messes up in the INSERT command then everything will be deleted.
But this code does nothing it doesn't insert or delete the data. May someone help me to fix this issue?
spojeni.Open();
SqlTransaction sqlTrans = spojeni.BeginTransaction();
try
{
string delCmdTxt = "TRUNCATE TABLE PLODINY";
SqlCommand cmdDel = spojeni.CreateCommand();
cmdDel.CommandText = delCmdTxt;
cmdDel.Transaction = sqlTrans;
cmdDel.ExecuteNonQuery();
string insert_sql =
"INSERT INTO PLODINY(PLODINA,CENAZAQ,MJ)VALUES(@PLODINA,@CENAZAQ,@MJ)";
SqlCommand sqlcom = spojeni.CreateCommand();
sqlcom.CommandText = insert_sql;
sqlcom.Transaction = sqlTrans;
foreach (DataGridViewRow row in dataGridView1.Rows)
{
sqlcom.Parameters.AddWithValue("@PLODINA", row.Cells["PLODINA"].Value);
sqlcom.Parameters.AddWithValue("@CENAZAQ", row.Cells["CENAZAQ"].Value);
sqlcom.Parameters.AddWithValue("@MJ", row.Cells["MJ"].Value);
sqlcom.ExecuteNonQuery();
sqlcom.Dispose();
}
sqlTrans.Commit();
}
catch (System.Data.SqlClient.SqlException)
{
sqlTrans.Rollback();
}
finally
{
spojeni.Close();
spojeni.Dispose();
}
this.Close();
Upvotes: 0
Views: 1024
Reputation: 127553
You are doing your parameters totally wrong, because the only thing in your catch
is the sqlTrans.Rollback();
you never see the errors you are getting, the first thing I would change is make that catch
catch (System.Data.SqlClient.SqlException)
{
sqlTrans.Rollback();
throw;
}
so you can now see the errors happen.
The next issue is if the table has any foreign key constraints your TRUNCATE TABLE
will fail, if it is failing you can simply replace it with
string delCmdTxt = "delete from PLODINY";
SqlCommand cmdDel = spojeni.CreateCommand();
cmdDel.CommandText = delCmdTxt;
cmdDel.Transaction = sqlTrans;
cmdDel.ExecuteNonQuery();
As to why your inserts are not working, you are disposing the command every instance of the for loop, you are also trying to re-add the parameters every time, reformat that loop to the following
string insert_sql = "INSERT INTO PLODINY(PLODINA,CENAZAQ,MJ)VALUES(@PLODINA,@CENAZAQ,@MJ)";
using(SqlCommand sqlcom = spojeni.CreateCommand())
{
sqlcom.CommandText = insert_sql;
sqlcom.Transaction = sqlTrans;
sqlcom.Parameters.Add("@PLODINA", SqlDbType.NVarChar); //Replace with whatever the correct datatypes are
sqlcom.Parameters.Add("@CENAZAQ", SqlDbType.NVarChar);
sqlcom.Parameters.Add("@MJ", SqlDbType.NVarChar);
foreach (DataGridViewRow row in dataGridView1.Rows)
{
sqlcom.Parameters["@PLODINA"] = row.Cells["PLODINA"].Value;
sqlcom.Parameters["@CENAZAQ"] = row.Cells["CENAZAQ"].Value;
sqlcom.Parameters["@MJ"] = row.Cells["MJ"].Value;
sqlcom.ExecuteNonQuery();
}
}
sqlTrans.Commit();
However your code can be made even better, if your DataGridView was backed by a DataTable via binding you could use a SqlTableAdapter instead, Lets say you load the table from the database, display it on the grid, and then you want to push back the updated information. With a DataTable it would be as simple as
private string _getDataQuery = "select PLODINA, CENAZAQ, MJ from PLODINY";
public void GetData(DataTable data)
{
//You do not need to call open here as SqlDataAdapter does it for you internally.
using(var spojeni = new SqlConnection(GetConnectionString())
using(var adapter = new SqlDataAdapter(_getDataQuery, spojeni)
{
data.Clear();
adapter.Fill(data);
}
}
public void UpdateData(DataTable data)
{
using(var spojeni = new SqlConnection(GetConnectionString())
using(var adapter = new SqlDataAdapter(_getDataQuery, spojeni)
using(var commandBuilder = new SqlCommandBuilder(adapter)
{
//This may or may not be nessesary for spojeni.BeginTransaction()
spojeni.Open();
using(var sqlTrans = spojeni.BeginTransaction())
{
adapter.SelectCommand.Transaction = sqlTrans;
adapter.UpdateCommand = commandBuilder.GetUpdateCommand();
adapter.UpdateCommand.Transaction = sqlTrans;
adapter.DeleteCommand = commandBuilder.GetDeleteCommand();
adapter.DeleteCommand.Transaction = sqlTrans;
adapter.InsertCommand = commandBuilder.GetInsertCommand()
adapter.InsertCommand.Transaction = sqlTrans;
try
{
adapter.Update(data);
sqlTrans.Commit();
}
catch
{
sqlTrans.Rollback();
throw;
}
}
}
}
Upvotes: 2
Reputation: 20494
Your problem is in your foreach
loop. You need to define your parameters before hand, and do not dispose the command object until you're all done with it. You can also use the Where
extension method to filter out any invalid rows from your data source since its a UI element.
string insert_sql = "INSERT INTO PLODINY(PLODINA,CENAZAQ,MJ)VALUES(@PLODINA,@CENAZAQ,@MJ)";
SqlCommand sqlcom = spojeni.CreateCommand();
sqlcom.CommandText = insert_sql;
sqlcom.Transaction = sqlTrans;
sqlcom.Parameters.Add("@PLODINA");
sqlcom.Parameters.Add("@CENAZAQ");
sqlcom.Parameters.Add("@MJ");
// some validation - add what you need.
var validRows = dataGridView1.Rows.Cast<DataGridViewRow>()
.Where(row => row.Cells["PLODINA"].Value != null);
foreach (DataGridViewRow row in validRows)
{
sqlcom.Parameters[0].Value = row.Cells["PLODINA"].Value;
sqlcom.Parameters[1].Value = row.Cells["CENAZAQ"].Value;
sqlcom.Parameters[2].Value = row.Cells["MJ"].Value;
sqlcom.ExecuteNonQuery();
}
sqlTrans.Commit();
sqlcom.Dispose();
Upvotes: 3
Reputation: 2106
Truncate Table only works if the table has not foreign key constraints... it's probably failing there and then rolling back the transaction in the catch statement...
Instead of Truncate try Delete From table and see if that fixes it...
Upvotes: 2