MySQL事务(提交和回滚)

3
以下是我用于 MySqlTransaction 的代码,它完美运行...但问题是,由于我只使用了单个的 mysqlcommand 实例,在其中必须使用唯一参数,这破坏了我的查询。是否有其他方法可以解决这个问题...
我尝试在每次查询后处理 cmd,但没有用.. :(
          con.Open()
            Dim sqlTran As MySqlTransaction = con.BeginTransaction()
            Dim cmd As MySqlCommand = con.CreateCommand()
            cmd.Transaction = sqlTran
            Dim str As String = Nothing
            Try
                cmd.CommandText = "SELECT myid FROM memaster where    Adate=@adate and ANo=@ano and ASource=@asrc"
                cmd.Parameters.AddWithValue("@adate", txt_bpass_adate.Text)
                cmd.Parameters.AddWithValue("@ano", txt_bpass_af.Text)
                cmd.Parameters.AddWithValue("@asrc", txt_bpass_asource.Text)
                str = cmd.ExecuteScalar()
                'cmd.Dispose()'
                If str Is Nothing Then

                    cmd.CommandText = "Insert into memaster (ADate,ANo,ASource) values (@aDate,@aNo,@aSRC)"
                    cmd.Parameters.AddWithValue("@aDate", txt_bpass_adate.Text)
                    cmd.Parameters.AddWithValue("@aNo", txt_bpass_af.Text)
                    cmd.Parameters.AddWithValue("@aSRC", txt_bpass_asource.Text)

     cmd.ExecuteNonQuery()
    End If
     sqlTran.Commit()

            Catch ex As Exception
                Try
                    sqlTran.Rollback()
                Catch ex1 As Exception

                End Try
            End Try

我实际上想在单个事务中执行多个查询,以便如果出现任何问题,我可以回滚它...

如果有人有其他方法,请与我分享这个概念...


     For index As Integer = 1 To 5
                    cmd.CommandText = "Insert into detail (ID,BNos,SNo) values (@FID1,@BNo,@SeqN1)"
                    cmd.Parameters.AddWithValue("@FID1", str)
                    cmd.Parameters.AddWithValue("@BNo", str1)
                    cmd.Parameters.AddWithValue("@SeqN1", txt_bpass_sqn1.Text)
                    cmd.ExecuteNonQuery()


                Next

当您处理一个实例时,您不能再使用它 - 连接已关闭并准备进行垃圾回收。 为什么您必须使用单个命令实例?我只是不理解您的问题,请尽量更好地解释。 - Rafal
你自己指定了问题:你正在使用一个 MySqlCommand,而应该使用两个。 - C.Evenhuis
@Rafal:嗯,就像我说的,我尝试过处理它,但没有起作用...无论如何,我为什么要使用单个实例,因为我必须维护整个事务直到结束,这样如果出现任何问题,我就可以回滚它...希望你现在明白了。 - neerajMAX
@neerajMAX 你可以在同一事务中使用单独的命令或相同的命令执行多个查询。为什么你会被限制只能使用一个 MySqlCommand 实例呢?正如其他人所提到的,你不能在 Dispose() 后使用一个对象。 - C.Evenhuis
@C.Evenhuis:你能告诉我怎么做吗?我其实对如何在多个命令中维护 "sqlTran"(我的代码中提到)感到困惑。 - neerajMAX
显示剩余4条评论
2个回答

5
为了在同一个事务中执行多个命令,请确保将事务对象分配给每个命令:
Dim selectCmd As MySqlCommand = con.CreateCommand()
Dim insertCmd As MySqlCommand = con.CreateCommand()

selectCmd.CommandText = "SELECT ..."
insertCmd.CommandText = "INSERT ..."

Dim sqlTran As MySqlTransaction = con.BeginTransaction()
Try
  selectCmd.Transaction = sqlTran
  insertCmd.Transaction = sqlTran

  ...selectCmd.ExecuteScalar()...
  ...insertCmd.ExecuteNonQuery()...

  sqlTran.Commit()
Catch
  sqlTran.Rollback()
End Try

正如其他人所提到的,如果您处理的对象是实现了IDisposable接口的对象,那么一般来说最好在使用完毕后立即调用Dispose()方法。在释放后,这些对象将无法再被使用。


@C Evenhuis:好的,我明白了...但是看一下我的问题中的for循环,我们应该怎么做呢?有什么建议吗? - neerajMAX

1
您可以使用Using关键字自动处理对象的释放。 我不懂VB,但我懂C#。 请将代码转换成VB。
using(MySqlConnection con= new MySqlConnection("connectionString"))
{
    con.Open();
    using(MysqlTransaction trans=con.BeginTransaction())
    {
        try
        {
            //command to executive query
            using(MysqlCommand cmd= new MySqlCommand("query", con, trans))
            {
                cmd.Parameters.AddWithValue("@parameter1", parametervalue1);
                cmd.Parameters.AddWithValue("@parameter2", parametervalue2);
                cmd.ExecutenonQuery();
                cmd.Parameters.Clear();
            }
            //command to execute query
            using(MysqlCommand cmd= new MySqlCommand("query", con, trans))
            {
                cmd.Parameters.AddWithValue("@parameter1", parametervalue1);
                cmd.Parameters.AddWithValue("@parameter2", parametervalue2);
                cmd.ExecutenonQuery();
                cmd.Parameters.Clear();
            }
            //command to execute query
            using(MysqlCommand cmd= new MySqlCommand("query", con, trans))
            {
                cmd.Parameters.AddWithValue("@parameter1", parametervalue1);
                cmd.Parameters.AddWithValue("@parameter2", parametervalue2);
                cmd.ExecutenonQuery();
                cmd.Parameters.Clear();
            }
            trans.Commit();
        }
        catch(Exception ex)
        {
            trans.Rollback();
        }
    }
}

如果插入失败是由于连接目的而关闭的,则回滚将无法工作,会生成异常,是否有其他方法可以进行回滚? - Andrew Alex
这是一个不好的解决方案 - 在C#中使用'using'语句会为您执行try catch,如果发生任何错误,将调用MySqlTransaction.cs.Dispose()来回滚事务。 - Mario
Mario,MySqlTransaction.cs.Dispose() 真的会回滚事务吗?如果是这样,在捕获异常后就不需要 trans.Rollback(),这将是最好的解决方案。对吗? - user2241289
这个问题已经有答案了:https://dev59.com/NXRB5IYBdhLWcg3wXmVI?rq=1 - user2241289

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接