22

我正在使用以下代码一次执行两个命令。我使用 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());
}

错误:

在此处输入图像描述

4

6 回答 6

37

您必须告诉您的 SQLCommand 对象使用事务:

cmd1.Transaction = transaction;

或在构造函数中:

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

确保也打开 connectionsql 对象。

但是您所做的只是 SELECT 语句。当您使用 INSERT、UPDATE 等类型的操作时,事务将受益更多。

于 2013-10-03T17:27:05.577 回答
29

下面的示例创建一个 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 类

于 2014-01-22T14:33:00.983 回答
9

您可以SqlTransactionSqlConnection.

并使用它来创建任意数量的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);

如果命令失败永远不会导致意外更改,请不要使用事务。

如果命令失败可能导致意外更改,则将它们放在 Try/Catch 块中,并在另一个Try/Catch 块中回滚操作。

为什么要再次尝试/捕获?根据MSDN

回滚事务时应始终使用Try/Catch异常处理。如果连接终止或事务已在服务器上回滚,则回滚会生成一个。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();
}

如果在调用 Commit 或 Rollback 之前处理该事务,则会回滚该事务。

所以你不必担心应用程序被关闭。

于 2017-07-20T21:47:56.923 回答
8

好吧,我不明白你为什么在做一个select.

当您从数据库中更改(添加、编辑或删除)数据时,事务非常有用。

删除事务,除非您使用insert,updatedelete语句

于 2013-10-03T17:30:48.057 回答
0

使用 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");
   }
 }
于 2016-08-07T11:42:32.850 回答
0

首先,您不需要事务,因为您只是在查询 select 语句,并且由于它们都是 select 语句,您可以将它们组合成一个由空格分隔的查询,并使用 Dataset 来获取检索到的所有表。这种方式更好,因为您只对数据库进行了一次事务,因为数据库事务很昂贵,因此您的代码更快。第二个你真的必须使用事务,只需将事务分配给 SqlCommand 就像

sqlCommand.Transaction = transaction;

并且只使用一个 SqlCommand 不要声明多个,因为变量会占用空间,而且我们也在使您的代码更高效的主题上,通过将 commandText 分配给不同的查询字符串并执行它们来做到这一点

sqlCommand.CommandText = "select * from table1";
sqlCommand.ExecuteNonQuery();
sqlCommand.CommandText = "select * from table2";
sqlCommand.ExecuteNonQuery();
于 2017-07-20T22:05:39.853 回答