在.NET中使用MySQL的ADO.Net驱动程序时,是否有必要为MySqlCommand
对象分配事务(例如,使用oCmd.Transaction = oTran
)或者是否足够MySqlConnection
1}}对象有一个打开的事务?在下面的代码中,我在连接上开始一个事务,使用单独的MySqlCommand
对象运行两个查询而不分配事务,然后回滚事务。在此示例中,UPDATE
都未提交到数据库。
MySqlConnection oConn = new MySqlConnection("Server=spet-il-cent-02;Port=3306;Database=test;Uid=test;Pwd=test123;CharSet=utf8;");
oConn.Open();
MySqlTransaction oTran = oConn.BeginTransaction();
MySqlCommand oCmd = oConn.CreateCommand();
oCmd.CommandText = "UPDATE testing SET testBalance = testBalance + 10 WHERE testID = 1";
oCmd.ExecuteNonQuery();
oCmd = oConn.CreateCommand();
oCmd.CommandText = "UPDATE testing SET testBalance = testBalance - 10 WHERE testID = 2";
oCmd.ExecuteNonQuery();
oTran.Rollback();
oConn.Close();
在运行时检查Transaction
的{{1}}属性时,我发现它是oCmd
。
显然,如果我调用null
,则会提交两个oTran.Commit()
语句。那么UPDATE
对象的Transaction
属性的目的是什么?它是否允许在单个连接上允许多个并发事务(不同的命令将绑定到不同的事务并且可以回滚或提交而不管彼此)?
答案 0 :(得分:0)
对于单个语句,您可以假装该属性不存在,以及Commit()
和Rollback()
方法。如果该属性不存在,则会自动提交单个语句。在问题的代码中,可以在更新testID = 1和更新testID = 2之间的短暂范围内运行查询,并且Rollback()
方法将无法完成任何操作。
要利用MySqlTransaction对象,您需要执行以下操作:
using (var Conn = new MySqlConnection("Server=spet-il-cent-02;Port=3306;Database=test;Uid=test;Pwd=test123;CharSet=utf8;"))
{
Conn.Open();
MySqlTransation Tran = Conn.BeginTransaction();
using (var Cmd = new MySqlCommand("UPDATE testing SET testBalance = testBalance + 10 WHERE testID = 1", Conn))
{
Cmd.Transaction = Tran;
Cmd.ExecuteNonQuery();
}
using (var Cmd = new MySqlCommand("UPDATE testing SET testBalance = testBalance + 10 WHERE testID = 2", Conn))
{
Cmd.Transaction = Tran;
Cmd.ExecuteNonQuery();
}
Tran.Rollback();
}
甚至更好:
using (var Conn = new MySqlConnection("Server=spet-il-cent-02;Port=3306;Database=test;Uid=test;Pwd=test123;CharSet=utf8;"))
using (var Cmd = new MySqlCommand("UPDATE testing SET testBalance = testBalance + 10 WHERE testID = @testID", Conn))
{
Conn.Open();
Cmd.Transaction = Conn.BeginTransaction();
Cmd.Parameteres.Add("@testID", MySqlDbType.Int32).Value = 1;
Cmd.ExecuteNonQuery();
Cmd.Parameters["testID"].Value = 2; //I can't remember at the moment if you need the "@" here or not
Cmd.ExecuteNonQuery();
Cmd.Transaction.Rollback();
}
当您想要保证多个操作是原子操作时,您需要事务。当您将事务分别分配给命令对象的每个实例,命令的每个实例使用相同的连接,并且连接在事务持续期间保持打开时,此方法有效。
此外,您可以将多个语句放入一个命令对象中:
string sql =
"BEGIN;" +
"UPDATE testing SET testBalance = testBalance + 10 WHERE testID = 1;" +
"UPDATE testing SET testBalance = testBalance - 10 WHERE testID = 2;" +
"COMMIT;";
using (var Conn = new MySqlConnection("Server=spet-il-cent-02;Port=3306;Database=test;Uid=test;Pwd=test123;CharSet=utf8;"))
using (var Cmd = new MySqlCommand(sql, Conn))
{
Conn.Open();
Cmd.ExecuteNonQuery();
}
这是首选方法,但有时代码的性质会阻止它,您必须使用MySqlTransaction
对象。