在C#.NET中回滚INSERT命令

时间:2012-04-13 19:20:50

标签: c#-4.0

我有一些混乱,我想清除它 - 我使用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();
            }

任何人都可以帮助我吗?

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

我对您的代码进行了2次修改

1)将BeginTransaction()移到for循环之外,以便所有10个INSERt语句都在一个事务中,如果你想要它们是 atomic

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

如果这不起作用,请告诉我。

答案 2 :(得分: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);
        }
    }
}