asp.net中使用Sqlserver事务时的体会,借鉴测试项目的脚本控制思想...

       很多企业应用系统,尤其是电商系统,事务的运用几乎是不可避免的.事务的作用黄岛主在这里就不多说了,百度一下自有详细资料...

       这里黄岛主主要说的是,通常适当地使用事务不但可以保证执行的一致性,而且也降低了维护的工作负担.  曾经一段时间因为没有好好的运用事务特性,不得不结合运行日志,订单状态..进行分析,之后加上诸如【订单同步】,【价格同步】等可供人工干预执行的按钮.

       出于之前对Visual studio自带的测试项目的了解,特意引入了类似的控制机制,对asp.net中应用sql事务进行了一定的封装...目前使用中还挺顺利的..如果有问题,欢迎讨论和拍砖..

     

 /// <summary>

        /// 功能简介:SqlDBUtility的内部类,用于辅助控制批量的sql语句按照事务执行

        /// 创建人:黄岛主([email protected])

        /// 联系地址:http://www.cnblogs.com/taohuadaozhu

        /// </summary>

        public class TransactionController

        {

            public class Command

            {

                private string commendText = "";

                public string CommendText

                {

                    get { return commendText; }

                }

                /// <summary>

                /// 期望的返回值,影响行数

                /// </summary>

                private int expectReturn = 0;

                /// <summary>

                /// 实际返回值,影响行数

                /// </summary>

                private int actualReturn = 0;

                /// <summary>

                /// true:严格要求实际返回值==期望返回值,false:要求实际返回值>期望返回值

                /// </summary>

                private bool isRequestEqual = true;

                private string tipsOnError = "";

                public string TipsOnError

                {

                    get { return tipsOnError; }

                    set { tipsOnError = value; }

                }

                /// <summary>

                /// 执行当前的Sql命令之后,实际返回的值,也就是影响行数

                /// </summary>

                public int ActualReturn

                {

                    get { return actualReturn; }

                    set { actualReturn = value; }

                }

                /// <summary>

                /// 一个Sql命令处理对象

                /// </summary>

                /// <param name="sCommendText">执行的sql语句</param>

                /// <param name="iExpectReturn">期望返回值</param>

                /// <param name="bRequestEqual">true:严格要求实际返回值==期望返回值,false:要求实际返回值>期望返回值</param>

                public Command(string sCommendText, int iExpectReturn, bool bRequestEqual, string sTipsWhenError)

                {

                    this.commendText = sCommendText;

                    this.expectReturn = iExpectReturn;

                    this.isRequestEqual = bRequestEqual;

                    this.tipsOnError = sTipsWhenError;

                }

                /// <summary>

                /// 检查是否执行成功

                /// </summary>

                /// <returns></returns>

                public bool IsSuccess()

                {

                    if (this.isRequestEqual)

                        return (actualReturn == expectReturn);

                    return (actualReturn > expectReturn);

                }

            }

            private List<Command> listCommand = null;

            public List<Command> ListCommand

            {

                get

                {

                    if (listCommand == null)

                        listCommand = new List<Command>();

                    return listCommand;

                }

            }

            public void Clear()

            {

                if (this.listCommand != null)

                    this.listCommand.Clear();

            }

            public bool IsSuccess()

            {

                if (listCommand == null)

                    return false;

                for (int i = 0; i < listCommand.Count; i++)

                {

                    if (listCommand[i].IsSuccess() == false)

                        return false;

                }

                return true;

            }

            /// <summary>

            /// 获得事务执行失败处的信息

            /// </summary>

            /// <returns></returns>

            public string GetErrorPointMssage()

            {

                if (listCommand == null)

                    return "";

                for (int i = 0; i < listCommand.Count; i++)

                {

                    if (listCommand[i].IsSuccess() == false)

                        return listCommand[i].TipsOnError;

                }

                return "";

            }

        }


  上面的代码,主要用于配置要一起执行(这些语句关联同一个业务操作,可能涉及多个表,但需要保证是在同一个数据库中)的sql命令对象Command,配置的过程中,注意指定每条sql语句预期的返回值(影响的行数). 以及是否需要将预期的返回值和实际的返回值进行对比(也就是那个bool类型的bRequestEqual参数了).  Command最后一个参数sTipsWhenError旨在指定如果失败了,终止并回滚sql命令后提示给用户的错误提示内容..

   具体结合ado.net进行检测,回滚,提交的代码如下,黄岛主在这里提示各位,这个可能需要根据你自己的SqlDBHelp类进行略微调整...

  

        /// <summary>

        /// 功能备注:用事务的方式执行多条SQL语句

        /// 创建人:黄岛主([email protected])

        /// 联系地址:http://www.cnblogs.com/taohuadaozhu

        /// </summary>

        /// <param name="trans_IsolationLevel">事务隔离级别设置,可以传入:IsolationLevel.ReadCommitted</param>

        /// <returns></returns>

        public static void RunSQLWithTransaction(TransactionController theTransactionTool, IsolationLevel trans_IsolationLevel, string sSQLConnectstr)

        {

            if (theTransactionTool == null

                || theTransactionTool.ListCommand.Count == 0)

                return;

            using (SqlConnection conn = new SqlConnection(sSQLConnectstr))

            {

                if (conn.State == ConnectionState.Broken || conn.State == ConnectionState.Closed)

                    conn.Open();

                using (SqlTransaction tran = conn.BeginTransaction(trans_IsolationLevel))

                {

                    using (SqlCommand sqlcm = new SqlCommand())

                    {

                        if (conn.State == ConnectionState.Closed || conn.State == ConnectionState.Broken)

                            conn.Open();

                        sqlcm.Connection = conn;

                        sqlcm.Transaction = tran;

                        try

                        {

                            for (int i = 0; i < theTransactionTool.ListCommand.Count; i++)

                            {

                                sqlcm.CommandText = theTransactionTool.ListCommand[i].CommendText;

                                theTransactionTool.ListCommand[i].ActualReturn = sqlcm.ExecuteNonQuery();

                                if (theTransactionTool.ListCommand[i].IsSuccess() == false)

                                {

                                    tran.Rollback();

                                    sqlcm.Dispose();

                                    if (conn.State == ConnectionState.Open)

                                        conn.Close();

                                    break;

                                }

                            }

                            if (theTransactionTool.IsSuccess())

                            {

                                tran.Commit();

                            }

                        }

                        catch (Exception ex)

                        {

                            tran.Rollback();

                            IOManager.Log4Net.Log4NetTools.Warn(string.Format("执行事务的回滚:" + ex.Message));

                        }

                        finally

                        {

                            sqlcm.Dispose();

                            tran.Dispose();

                            if(conn.State==ConnectionState.Open)

                            conn.Close();

                        }

                    }

                }

            }

        }

     好了,具体的代码其实不重要,关键是向大家分享一下这个借鉴测试项目常用脚本的事务辅助控制机制...

你可能感兴趣的:(sqlserver)