在 ADO.net SQL 中使用事务

Kok*_*Nut 3 c# sql-server ado.net

我是 ADO 的新手,所以我想问一下我使用事务是否正确。这里是代码片段

string SQL1 = "INSERT INTO tbl_cust(cust_id,cust_name) values ('000001','YoungMcD') ";
string SQL2 = "UPDATE tbl_cust SET custname='OldMcDonald' WHERE cust_id='000001'";
string SQL3 = "SELECT * FROM tbl_supplier WHERE supplier_code ='000001'";

// write connstring
string conn = System.Configuration.ConfigurationManager.ConnectionStrings["connstr"].ConnectionString;
// end of connection string

// setting connection
SqlConnection db = new SqlConnection(conn);
SqlTransaction transaction1;

db.Open();
transaction1 = db.BeginTransaction();

try
{
    // insert to table
    SqlCommand Com1 = new SqlCommand(SQL1, db, transaction1);
    Com1.ExecuteNonQuery();

    SqlCommand Com2 = new SqlCommand(SQL2, db, transaction1);
    Com2.ExecuteNonQuery();

    SqlCommand Com3 = new SqlCommand(SQL3, db, transaction1);
    Com3.ExecuteNonQuery();

    transaction1.Commit();

    db.Close();
}
catch
{
    transaction1.Rollback();
    db.Close();
    msg = "error";
    goto endret;
}
Run Code Online (Sandbox Code Playgroud)

对于交易,我应该使用

SqlCommand Com1 = new SqlCommand(SQL1, db, transaction1);
Run Code Online (Sandbox Code Playgroud)

代替

SqlCommand Com1 = new SqlCommand(SQL1, db);
Run Code Online (Sandbox Code Playgroud)

因为我已经在try{}声明之前声明开始交易

编辑:

我明白了,First 语法是适用的,但是如何有效地使用 ADO?。我觉得这种方式太直接了。

我发现自己一直在这样做以插入参数,例如:

string SQL1 = "INSERT INTO tbl_cust(cust_id,cust_name) values ('" + param1 +"','"+ param2 +"') ";
Run Code Online (Sandbox Code Playgroud)

Kok*_*Nut 6

自去年以来发生了很多事情。在这里,我试图简化答案。

string ConnStr = System.Configuration.ConfigurationManager.ConnectionStrings["connstr"].ConnectionString;
string SQL1 = "INSERT INTO tbl_cust(cust_id,cust_name) values ('000001','YoungMcD') ";
string SQL2 = "UPDATE tbl_cust SET custname='OldMcDonald' WHERE cust_id='000001'";

using (SqlConnection conn = new SqlConnection(ConnStr))
{
    SqlTransaction transaction = null;
    try
    {
        conn.Open();
        transaction = conn.BeginTransaction();
        using (SqlCommand cmd = new SqlCommand(SQL1, conn, transaction)) { cmd.ExecuteNonQuery(); }
        using (SqlCommand cmd = new SqlCommand(SQL2, conn, transaction)) { cmd.ExecuteNonQuery(); }
        transaction.Commit();
        savestats = true;
    }
    catch (Exception ex)
    {
         // 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.
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

事务在外部声明的原因,try{}以便我们可以在catch{}.

这段代码的失败之处在于conn.Open(),无论出于何种原因发生错误时,都transaction.Rollback()将导致异常。

这就是为什么另一个try{} catch{}添加来处理它的原因。


Wil*_*ras 5

您应该使用一个命令,并将您的连接包装在一个Using块中,以便正确处理它。此外,您应该在事务提交后通过执行 SqlDataReader 从 tbl_supplier 中读取数据。我假设您只是想知道事务提交后有多少行受到影响。

这是您的代码的简化版本。

var conn = System.Configuration.ConfigurationManager.ConnectionStrings["connstr"].ConnectionString;
string SQL1 = "INSERT INTO tbl_cust(cust_id,cust_name) values ('000001','YoungMcD') ";
string SQL2 = "UPDATE tbl_cust SET custname='OldMcDonald' WHERE cust_id='000001'";

using (SqlConnection connection = new SqlConnection(conn))
{
    connection.Open();
    SqlTransaction sqlTran = connection.BeginTransaction();
    SqlCommand command = connection.CreateCommand();
    command.Transaction = sqlTran;

    try
    {
        command.CommandText = SQL1;
        int rowsAffected = command.ExecuteNonQuery();
        command.CommandText = SQL2;
        rowsAffected += command.ExecuteNonQuery();
        transaction.Commit();
    }
    catch (Exception ex1)
    {
        // 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.
        }
    }
}
Run Code Online (Sandbox Code Playgroud)