2017-06-14 6 views
0

.NETでMySQL用ADO.Netドライバを使用する場合は、を使用してMySqlCommandオブジェクトにトランザクションを割り当てる必要がありますか、またはMySqlConnectionオブジェクトにオープントランザクションがあるだけで十分ですか?以下のコードでは、トランザクションを割り当てずに別のMySqlCommandオブジェクトで2つのクエリを実行し、トランザクションをロールバックして接続を開始します。この例では、どちらも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(); 

実行時にoCmdTransactionプロパティを確認すると、私はそれが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を使用する必要があります代わりにオブジェクト。

関連する問題