Я разрабатываю небольшое настольное приложение, используя VS.net и SQL Server.
Я использую SqlTransaction в своем коде:
SqlTransaction tran = null;
SqlCommand cmd = new SqlCommand();
int lstInsSubjId = -1;
try
{
using (SqlConnection con = new SqlConnection(connectionString))
{
con.Open();
tran = con.BeginTransaction("Transaction1");//Transaction begin
tran.Save("Savepoint_1");//Savepoint 1
string sql1 = @"insSubject";
cmd = new SqlCommand(sql1, con, tran);
cmd.Parameters.Add("@lstInsSubjId", SqlDbType.Int).Direction = ParameterDirection.Output;
cmd.Parameters.Add("@sub_name", SqlDbType.VarChar).Value = txtSubjectName.Text.Trim();
cmd.CommandType = CommandType.StoredProcedure;
tran.Save("Savepoint_2");//Savepoint 2
cmd.ExecuteNonQuery();
lstInsSubjId = Convert.ToInt32(cmd.Parameters["@lstInsSubjId"].Value);
for (int i = 0; i < clbClasses.CheckedItems.Count; i++)
{
int clsId = Convert.ToInt32(((DataRowView)clbClasses.CheckedItems[i]).Row["c_id"].ToString());
cmd.CommandText = @"INSERT INTO tblClassSubjectMap_mavis(c_id, sub_id)
VALUES(@c_id, @sub_id)";
cmd.Parameters.Add("@c_id", SqlDbType.Int).Value = clsId;
cmd.Parameters.Add("@sub_id", SqlDbType.Int).Value = lstInsSubjId;
cmd.CommandType = CommandType.Text;
//tran.Save("Savepoint_3");//Savepoint 3
cmd.ExecuteNonQuery();
}
tran.Commit();//Transaction commit
MessageBox.Show("Records added", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
txtSubjectName.Text = "";
txtSubjectName.Focus();
frmSubjectBrows.subList.bindListView();
}
}
catch (SqlException ex)
{
if (tran != null)
{
tran.Rollback();
MessageBox.Show(ex.Message.ToString() + "\nTransaction Rolledback", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
}
Ближе к концу кода, в цикле for, если есть более одного проверенного элемента, т.е. если он выполняет итерацию/цикл более одного раза, он выдает ошибку, и транзакция никогда не фиксируется. Однако, если он зацикливается только один раз, ошибки нет, и транзакции фиксируются.
Сообщение об ошибке:
An unhandled exception of type 'System.InvalidOperationException' occurred in System.Data.dll
Additional information: This SqlTransaction has completed; it is no longer usable.
При поиске ответа в Интернете некоторые решения говорят, что такая ошибка может возникнуть, если транзакция резко закрывается до совершения. Но я не понимаю, как здесь сделка закрывается.
Кто-нибудь может сказать, что происходит не так? Заранее спасибо.





используйте для каждой команды новый экземпляр sqlcommand, см. пример на
https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqltransaction?view=netframework-4.8
попробуйте этот код:
int lstInsSubjId = -1;
try
{
using (SqlConnection con = new SqlConnection(connectionString))
{
con.Open();
SqlCommand cmd = connection.CreateCommand();
SqlTransaction tran = con.BeginTransaction("Transaction1");//Transaction begin
cmd.Connection = cmd;
cmd.Transaction = tran;
tran.Save("Savepoint_1");//Savepoint 1
cmd.CommandText = @"insSubject";
cmd.Parameters.Add("@lstInsSubjId", SqlDbType.Int).Direction = ParameterDirection.Output;
cmd.Parameters.Add("@sub_name", SqlDbType.VarChar).Value = txtSubjectName.Text.Trim();
cmd.CommandType = CommandType.StoredProcedure;
tran.Save("Savepoint_2");//Savepoint 2
cmd.ExecuteNonQuery();
lstInsSubjId = Convert.ToInt32(cmd.Parameters["@lstInsSubjId"].Value);
for (int i = 0; i < clbClasses.CheckedItems.Count; i++)
{
int clsId = Convert.ToInt32(((DataRowView)clbClasses.CheckedItems[i]).Row["c_id"].ToString());
SqlCommand cmd2 = connection.CreateCommand();
cmd2.Connection = cmd2;
cmd2.Transaction = tran;
cmd2.CommandText = @"INSERT INTO tblClassSubjectMap_mavis(c_id, sub_id)
VALUES(@c_id, @sub_id)";
cmd2.Parameters.Add("@c_id", SqlDbType.Int).Value = clsId;
cmd2.Parameters.Add("@sub_id", SqlDbType.Int).Value = lstInsSubjId;
cmd2.CommandType = CommandType.Text;
//tran.Save("Savepoint_3");//Savepoint 3
cmd2.ExecuteNonQuery();
}
tran.Commit();//Transaction commit
поместите вашу транзакцию в «Выписку об использовании».