C# 事物控制

发布时间 2023-03-31 09:20:40作者: 天上星

1.本地事物

即一个Connection并连接到单一的数据库中。用法如下:

static void LocalTranslate()
        {
            using (SqlConnection conn = new SqlConnection(args[0]))
            {
                conn.Open();
                string sql1 = "update Table1 set column1='NewValue1' where ID=0";
                string sql2 = "Insert into Table2 values(18,'rt','ghfg')";

                SqlTransaction sqlTransaction = conn.BeginTransaction();  //开启本地事物
                SqlCommand cmd = conn.CreateCommand();

                cmd.Transaction = sqlTransaction; //指定Command事物 
                try
                {
                    cmd.CommandText = sql1;
                    cmd.ExecuteNonQuery();

                    cmd.CommandText = sql2;
                    cmd.ExecuteNonQuery();

                    sqlTransaction.Commit();  //提交事物
                }
                catch (Exception ex)
                {
                    sqlTransaction.Rollback();//回滚事物                   
                }
            }
        }

2.分布式事物

即多个Connection并连接到不同的DB中,比如一个Connection连接MSSQL,另一个Connection连接到Oracle。需用到TranscationScope,它会自动提升为分布式事物,并且不用特别指定Connection及Command事物名称,

只要这些操作在TranscationScop块中。在执行完后调用Complete方法即可,如果之前遇到Exception就会自动回滚事物并不会再调用Complete方法。

static void DistributeTranslate()
        {
            //需引用System.Transaction.dll并using,开启分布式事物
            using (TransactionScope scope = new TransactionScope()) 
            {
                using(SqlConnection conn1=new SqlConnection("Server1Connection")) //指定第一个DB库的连接
                {
                    
                    try
                    {
                        conn1.Open();//打开连接会自动将其登记到TransactionScope作为轻量级事务。
                        SqlCommand cmd1 = conn1.CreateCommand(); 
                        cmd1.CommandText = "Insert into server1.dbo.table values(...) ";
                        cmd1.ExecuteNonQuery();

                        using (SqlConnection conn2 = new SqlConnection("Server2Connection"))//指定第二个DB库的连接,要嵌套到第一个语句块中
                        {
                            conn2.Open(); //打开第二个连接时事务被提升为完全分布式。
                            SqlCommand cmd2 = conn2.CreateCommand();
                            cmd2.CommandText = "Update server2.dbo.table2...";
                            try
                            {
                                cmd2.ExecuteNonQuery();
                            }
                            catch (Exception ex)
                            {
                                //log the ex.message
                            }
                        }
                    }
                    catch(Exception ex)
                    {
                        // log the ex.message,不用调用return退出就会自动回滚
                    }                   

                }

       
                //如果引发了异常,则Complete不会被调用,并且事务被回滚。
                scope.Complete() ;
            }