Причина ошибки «SqlTransaction завершена» - PullRequest
0 голосов
/ 08 июня 2019

Я занимаюсь разработкой небольшого настольного приложения с использованием 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, если есть более одного проверенного элемента, т.е. если он повторяется / повторяется более одного раза, то онвыдает ошибку и транзакция никогда не совершается.Однако, если цикл повторяется только один раз, ошибки не возникает и транзакции фиксируются.

Сообщение об ошибке:

Произошло необработанное исключение типа 'System.InvalidOperationException' в системе.Data.dll

Дополнительная информация: Эта SqlTransaction завершена;его больше нельзя использовать.

При поиске ответа в Интернете некоторые решения утверждают, что такая ошибка может возникать, если транзакция внезапно закрывается перед ее фиксацией.Но я не понимаю, как здесь транзакция закрывается.

Может кто-нибудь сказать, пожалуйста, что идет не так?Заранее спасибо.

1 Ответ

1 голос
/ 08 июня 2019

используйте для каждой команды новый экземпляр 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...