1

ADO.NETを使用してデータベースに値を挿入しています。5番目のアイテムのデータを挿入しているときにエラーが発生した場合、10個のアイテムを挿入したいとしましょう。データベースに挿入したものはすべてロールバックする必要があります。

Transaction と Rollback メソッドの概念を読み、プログラムに実装しようとしましたが、それでも 4 つの項目が挿入され、5 番目の項目のエラー メッセージが表示されます。挿入クエリをロールバックしません。

トランザクションとロールバックの方法で問題は解決しましたか、それとも他の方法を使用する必要がありますか。

ここに私のコードがあります、

for (int i = 0; i < itemLength - 1; i++)
            {
                //--- Start local transaction ---
                myTrans = Class1.conn.BeginTransaction();

                //--- Assign transaction object and connection to command object for a pending local transaction ---
                _insertQry = Class1.conn.CreateCommand();
                _insertQry.Connection = Class1.conn;
                _insertQry.Transaction = myTrans;

                _insertQry.CommandText = "INSERT INTO Product_PropertyValue(ItemNo, PropertyNo, ValueNo) VALUES (@ItemNo, @PropertyNo, @ValueNo)";

                //_insertQry = new SqlCommand("INSERT INTO Product_PropertyValue(ItemNo, PropertyNo, ValueNo) VALUES (@ItemNo, @PropertyNo, @ValueNo)", Class1.conn);

                _insertQry.Parameters.AddWithValue("@ItemNo", _itemNo[i]);
                _insertQry.Parameters.AddWithValue("@PropertyNo", _propNo);
                _insertQry.Parameters.AddWithValue("@ValueNo", _propValue);

                _insertQry.ExecuteNonQuery();
                myTrans.Commit();
            }

誰でも私を助けることができますか?

4

3 に答える 3

2

アトミックコミットを達成しようとしているようです。完全に挿入されるか、まったく挿入されません。

次のようなものを試してください

SqlTransaction objTrans = null;
        using (SqlConnection objConn = new SqlConnection(strConnString))
        {
            objConn.Open();
            objTrans = objConn.BeginTransaction();
            SqlCommand objCmd1 = new SqlCommand("insert into tbExample values(1)", objConn);
            SqlCommand objCmd2 = new SqlCommand("insert into tbExample values(2)", objConn);
            try
            {
                objCmd1.ExecuteNonQuery();
                objCmd2.ExecuteNonQuery();
                objTrans.Commit();
            }
            catch (Exception)
            {
                objTrans.Rollback();
            }
            finally
            {
                objConn.Close();
            }

http://www.codeproject.com/Articles/10223/Using-Transactions-in-ADO-NETも ご覧ください。

于 2012-04-13T19:38:41.890 に答える
1

私はあなたのコードに2つの変更を加えました

1) BeginTransaction() を for ループの外に移動して、10 個の INSERt ステートメントすべてが単一のトランザクションになるようにします。これは、アトミックにしたい場合に必要なことです。

2) エラーが発生した場合にロールバックできるように、TRY/CATCH ブロックを追加しました。

        //--- Start local transaction ---
        myTrans = Class1.conn.BeginTransaction();
        bool success = true;

        try
        {
            for (int i = 0; i < itemLength - 1; i++)
            {
                //--- Assign transaction object and connection to command object for a pending local transaction ---
                _insertQry = Class1.conn.CreateCommand();
                _insertQry.Connection = Class1.conn;
                _insertQry.Transaction = myTrans;

                _insertQry.CommandText = "INSERT INTO Product_PropertyValue(ItemNo, PropertyNo, ValueNo) VALUES (@ItemNo, @PropertyNo, @ValueNo)";

                //_insertQry = new SqlCommand("INSERT INTO Product_PropertyValue(ItemNo, PropertyNo, ValueNo) VALUES (@ItemNo, @PropertyNo, @ValueNo)", Class1.conn);

                _insertQry.Parameters.AddWithValue("@ItemNo", _itemNo[i]);
                _insertQry.Parameters.AddWithValue("@PropertyNo", _propNo);
                _insertQry.Parameters.AddWithValue("@ValueNo", _propValue);

                _insertQry.ExecuteNonQuery();
            }
        }
        catch (Exception ex)
        {
            success = false;
            myTrans.Rollback();
        }

        if (success)
        {
            myTrans.Commit();
        }

これが機能しない場合はお知らせください。

于 2012-04-13T20:11:07.810 に答える
0

あなたは正しい道を進んでいます。ADO.NETはトランザクションをサポートしているため、エラーをロールバックできます。

ここにコードを投稿すると、より具体的なガイダンスが得られます。ただし、質問は非常に一般的であるため、MSDNが提供するテンプレートに従うことをお勧めします。

using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();

    // Start a local transaction.
    SqlTransaction sqlTran = connection.BeginTransaction();

    // Enlist a command in the current transaction.
    SqlCommand command = connection.CreateCommand();
    command.Transaction = sqlTran;

    try
    {
        // Execute two separate commands.
        command.CommandText =
          "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong size')";
        command.ExecuteNonQuery();
        command.CommandText =
          "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong color')";
        command.ExecuteNonQuery();

        // Commit the transaction.
        sqlTran.Commit();
        Console.WriteLine("Both records were written to database.");
    }
    catch (Exception ex)
    {
        // Handle the exception if the transaction fails to commit.
        Console.WriteLine(ex.Message);

        try
        {
            // Attempt to roll back the transaction.
            sqlTran.Rollback();
        }
        catch (Exception exRollback)
        {
            // Throws an InvalidOperationException if the connection 
            // is closed or the transaction has already been rolled 
            // back on the server.
            Console.WriteLine(exRollback.Message);
        }
    }
} 
于 2012-04-13T19:42:36.607 に答える