嵌套事务范围与C#的混合隔离级别

时间:2015-10-05 19:10:44

标签: c# sql-server transactions transactionscope distributed-transactions

我对事务范围和隔离级别有一点疑问......所以我现在知道范围内的所有内容可能会也可能不会出现在根范围内,(拥有一个)这个条件取决于某些条件。

方案

我有一张表A,我想阻止它直到整个transcope提交。我不希望任何其他转发更新,删除或插入,因此此交易将被隔离为可序列化,并且表B将插入一些关键值A但是这个(b)不需要被阻止因为有些用户正在查询提交的数据甚至是脏数据**因此我已经理解了这个需求,所以这将是默认的隔离读取未提交。这是一种轻量级的事务

  1. 如果选择Required作为内部TransactionScopeOption,它将加入其外部事务。这意味着如果外部事务已提交,则内部事务将提交,如果外部事务被回滚,则内部事务将被回滚。但如果内心失败怎么办?外部也会回滚吗?
  2. 内部交易隔离级别会受到尊重吗?一个阻止,其他没有。
  3. 如何捕捉异常?
  4. 我的程序也不需要包含交易吗?这只会使事务范围和隔离级别的复杂性加倍。
  5. 这是我的代码:

    public bool nestedTranComplete(SomeModel thatModel)         {

            int secName = 0;
            List<int> IDsList = new List<int>();
            var opts = new TransactionOptions
            {
                IsolationLevel = System.Transactions.IsolationLevel.Serializable,
                Timeout = new TimeSpan(0, 0, 9000)
            };
            var opts2 = new TransactionOptions
                    {
                        IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted,
                        Timeout = new TimeSpan(0, 1, 0)
                    };
    
            try
            {
                using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew, opts))
                {
                    using (SqlConnection con = new SqlConnection(SqlconnectionString))
                    {
                        using (SqlCommand cmdConsecutiveID = new SqlCommand("usp_GetNewSeqVal", con))
                        {
                            cmdConsecutiveID.CommandType = CommandType.StoredProcedure;
                            cmdConsecutiveID.Parameters.Add(new SqlParameter { SqlDbType = SqlDbType.VarChar, 
                                ParameterName = "SeqName" }).Value = "Someprocess";
                            using (SqlDataReader readr = cmdConsecutiveID.ExecuteReader(CommandBehavior.SingleRow))
                            {
                                readr.Read();
                                secName = readr.GetInt32(0);
                            }
                            if (secName == 0)
                            {
                                throw new ArgumentException("no success on getting the new number", "SeqName");
                            }
                        }
                    }
                    using (TransactionScope DependingBlockingScope = new TransactionScope(TransactionScopeOption.Required, opts2))
                    {
    
                        using (SqlConnection con2 = new SqlConnection(SqlconnectionString))
                        {
                            foreach (var Mynumber in thatModel.IDlists)
                            {
                                using (SqlCommand cmd = new SqlCommand("InsertProces", con, tran))
                                {
                                    cmd.CommandType = CommandType.StoredProcedure;
                                    cmd.Parameters.Add(new SqlParameter { SqlDbType = SqlDbType.Int, 
                                        ParameterName = "one" }).Value = Mynumber;
                                    cmd.Parameters.Add(new SqlParameter { SqlDbType = SqlDbType.Int,
                                        ParameterName = "two" }).Value = thatModel.someprop;
                                    cmd.Parameters.Add(new SqlParameter { SqlDbType = SqlDbType.Int, 
                                        ParameterName = "secnumber" }).Value = secName;// here i obtain the the result of the last transaction
                                    using (SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
                                    {
                                        if (reader.HasRows)
                                        {
                                            reader.Read();
                                            int theid = reader.GetInt32(0);
                                            IDsList.Add(theid);
    
                                        }
                                    }
                                }
                            }
    
                            //if (thatModel.IDlists.Count == IDsList.Count)
                            //{
                            //    return true;//or leave this alone  in order to the root transaction scope complete
                            //DependingBlockingScope.RollBack();
                            //}
                            //else
                            //{
                            //    throw new ArgumentException("no se consiguio el siguiente numero consecutivo", "SeqName");
                            //}
                        }
                        DependingBlockingScope.Complete();
                    }
                    scope.Complete();
                }
            }
            catch (Exception ex)
            {
                if (ex is SqlException || ex is ArgumentException)
                {
                    return false;
                }
                //roll back everyting and inform
            }
            return false;
        }
    

0 个答案:

没有答案