2017-06-14 62 views
0

在.NET中爲MySQL使用ADO.Net驅動程序時,是否需要將事務分配給MySqlCommand對象(例如,使用oCmd.Transaction = oTran)還是足以使MySqlConnection對象具有開放事務?在下面的代碼中,我在連接上開始一個事務,在不分配事務的情況下運行兩個帶有單獨MySqlCommand對象的查詢,然後回滾事務。在這個例子中,UPDATE都沒有被提交給數據庫。.NET MySqlCommand.Transaction - 它的用途是什麼?

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(); 

當檢查oCmd在運行時Transaction財產,我看到它是null

很明顯,如果我打電話給oTran.Commit(),那麼兩個UPDATE陳述都被提交。那麼MySqlCommand對象的Transaction屬性的目的是什麼?是否允許在單個連接上使用多個併發事務(其中不同的命令將綁定到不同的事務,並且可以回滾或提交而不考慮彼此)?

回答

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對象。

相關問題