web-dev-qa-db-ja.com

C#でsqltransactionを使用する方法

次のコードを使用して、2つのコマンドを一度に実行しています。 sqltransactionを使用して、すべてのコマンドが実行またはロールバックされるようにしました。「トランザクション」なしでプログラムを実行すると、正しく実行されますが、「トランザクション」を使用するとエラーが表示されます。私のコードは次のとおりです。

SqlTransaction transaction = connectionsql.BeginTransaction();

try
{
    SqlCommand cmd1 = new SqlCommand("select account_name from master_account where NOT account_name = 'BANK' AND NOT account_name = 'LOAN'", connectionsql);
    SqlDataReader dr1 = cmd1.ExecuteReader();
    while (dr1.Read())
    {
        comboBox1.Items.Add(dr1[0].ToString().Trim());
    }
    cmd1.Dispose();
    dr1.Dispose();

    SqlCommand cmd2 = new SqlCommand("select items from rate",connectionsql);
    SqlDataReader dr2 = cmd2.ExecuteReader();
    while (dr2.Read())
    {
        comboBox2.Items.Add(dr2[0].ToString().Trim());
    }
    cmd2.Dispose();
    dr2.Dispose();
    transaction.Commit();

    dateTimePicker4.Value = dateTimePicker3.Value;
}
catch(Exception ex)
{
    transaction.Rollback();
    MessageBox.Show(ex.ToString());
}

およびエラー:

enter image description here

19
Sonu_Orai

トランザクションを使用するようにSQLCommandオブジェクトに指示する必要があります。

cmd1.Transaction = transaction;

またはコンストラクター内:

SqlCommand cmd1 = new SqlCommand("select...", connectionsql, transaction);

Connectionsqlオブジェクトも必ず開いてください。

ただし、実行しているのはSELECTステートメントのみです。 INSERT、UPDATEなどのタイプのアクションを使用すると、トランザクションのメリットが大きくなります。

34
LarsTech

次の例では、SqlConnectionとSqlTransactionを作成します。また、BeginTransaction、Commit、およびRollbackメソッドの使用方法も示します。エラーが発生した場合、または最初にコミットされずに破棄された場合、トランザクションはロールバックされます。 Try/Catchエラー処理は、トランザクションをコミットまたはロールバックしようとしたときにエラーを処理するために使用されます。

private static void ExecuteSqlTransaction(string connectionString)
{
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();

        SqlCommand command = connection.CreateCommand();
        SqlTransaction transaction;

        // Start a local transaction.
        transaction = connection.BeginTransaction("SampleTransaction");

        // Must assign both transaction object and connection 
        // to Command object for a pending local transaction
        command.Connection = connection;
        command.Transaction = transaction;

        try
        {
            command.CommandText =
                "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')";
            command.ExecuteNonQuery();
            command.CommandText =
                "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')";
            command.ExecuteNonQuery();

            // Attempt to commit the transaction.
            transaction.Commit();
            Console.WriteLine("Both records are written to database.");
        }
        catch (Exception ex)
        {
            Console.WriteLine("Commit Exception Type: {0}", ex.GetType());
            Console.WriteLine("  Message: {0}", ex.Message);

            // Attempt to roll back the transaction. 
            try
            {
                transaction.Rollback();
            }
            catch (Exception ex2)
            {
                // This catch block will handle any errors that may have occurred 
                // on the server that would cause the rollback to fail, such as 
                // a closed connection.
                Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType());
                Console.WriteLine("  Message: {0}", ex2.Message);
            }
        }
    }
}

SqlTransaction Class を参照してください

22
Ramashankar

SqlTransactionからSqlConnectionを作成できます。

それを使用して、任意の数のSqlCommandsを作成します

SqlTransaction transaction = connection.BeginTransaction();
var cmd1 = new SqlCommand(command1Text, connection, transaction);
var cmd2 = new SqlCommand(command2Text, connection, transaction);

または

var cmd1 = new SqlCommand(command1Text, connection, connection.BeginTransaction());
var cmd2 = new SqlCommand(command2Text, connection, cmd1.Transaction);

コマンドの失敗neverが予期しない変更を引き起こす場合do n'tトランザクションを使用。

コマンドの失敗mightが予期しない変更を引き起こし、それらをTry/Catchブロックに入れ、anotherで操作をロールバックする場合Try/Catchブロック。

[〜#〜] msdn [〜#〜] によると:

Try/Catch例外処理常に使用する必要がありますwhenトランザクションのロールバック。接続が終了した場合、またはサーバーでトランザクションがすでにロールバックされている場合、ロールバックはInvalidOperationExceptionを生成します。

サンプルコードを次に示します。

string connStr = "[connection string]";
string cmdTxt = "[t-sql command text]";

using (var conn = new SqlConnection(connStr))
{
    conn.Open();
    var cmd = new SqlCommand(cmdTxt, conn, conn.BeginTransaction());


    try
    {
        cmd.ExecuteNonQuery();
        //before this line, nothing has happened yet
        cmd.Transaction.Commit();
    }
    catch(System.Exception ex)
    {
        //You should always use a Try/Catch for transaction's rollback
        try
        {
            cmd.Transaction.Rollback();
        }
        catch(System.Exception ex2)
        {
            throw ex2;
        }
        throw ex;
    }

    conn.Close();
}

コミットの前にdisposedである場合、トランザクションはrolled backまたはロールバックが呼び出されます。

したがって、アプリが閉じられることを心配する必要はありません。

6
Bizhan

さて、selectを作成する場合にトランザクションを使用する理由はわかりません。

トランザクションは、データベースからデータを変更(追加、編集、または削除)するときに役立ちます。

insertupdate、またはdeleteステートメントを使用しない限り、トランザクションを削除します

6
Snake Eyes

SQLトランザクションによる更新または削除

 private void SQLTransaction() {
   try {
     string sConnectionString = "My Connection String";
     string query = "UPDATE [dbo].[MyTable] SET ColumnName = '{0}' WHERE ID = {1}";

     SqlConnection connection = new SqlConnection(sConnectionString);
     SqlCommand command = connection.CreateCommand();
     connection.Open();
     SqlTransaction transaction = connection.BeginTransaction("");
     command.Transaction = transaction;
     try {
       foreach(DataRow row in dt_MyData.Rows) {
         command.CommandText = string.Format(query, row["ColumnName"].ToString(), row["ID"].ToString());
         command.ExecuteNonQuery();
       }
       transaction.Commit();
     } catch (Exception ex) {
       transaction.Rollback();
       MessageBox.Show(ex.Message, "Error");
     }
   } catch (Exception ex) {
     MessageBox.Show("Problem connect to database.", "Error");
   }
 }
0
Masoud Siahkali

まず、selectステートメントを照会するだけであり、両方ともselectステートメントであるため、スペースで区切られた1つのクエリにそれらを結合し、Datasetを使用してすべてのテーブルを取得できるため、トランザクションは必要ありません。データベーストランザクションは高価であり、コードが高速であるため、データベースに対してトランザクションを1つだけ作成したため、この方法の方が優れています。次に、トランザクションを使用する必要があります。トランザクションをSqlCommandに割り当てるだけです。

sqlCommand.Transaction = transaction;

また、1つのSqlCommandを使用するだけで、複数の変数を宣言することはできません。変数はスペースを消費し、コードをより効率的にすることもテーマになっているため、commandTextを別のクエリ文字列に割り当てて

sqlCommand.CommandText = "select * from table1";
sqlCommand.ExecuteNonQuery();
sqlCommand.CommandText = "select * from table2";
sqlCommand.ExecuteNonQuery();
0
lulliezy