当前位置:编程学习 > C#/ASP.NET >>

关于TransactionOptions事务的应用,具体应该怎么用和注意事项

最近做项目,碰到一个问题,就是多个用户预约同一条信息,然后其中一个预约成功,但另一个没预约成功,但是都同时把数据保存到连个表当中了。就是并发状态导致数据不统一,然后考虑到用事务来处理,当时第一个想到的是在数据库上应用数据库的事务处理,但是现在的项目是用三层架构来写的,各个表都有各自的连接数据库的方法和业务逻辑,在数据库上用事务的话,需要连接数据库的时候放在一起才能用事务,所以就在网上查找到.net有单独的事务处理类,就是TransactionOptions类,在网上查找了些资料,
我也照着用在了我的项目里,但是我放在事务里的是一个一个的方法,就是预约要处理的代码,就是这样


         public void Update()
        {
                   //设置事务范围
                    TransactionOptions transactionOption = new TransactionOptions();
                    //设置事务隔离级别
                    transactionOption.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted; //不可以在事务期间读取可变数据,但是可以修改它
                    //RepeatableRead  可以在事务期间读取可变数据,但是不可以修改。 可以在事务期间添加新数据。
                    // 设置事务超时时间为60秒
                    //  transactionOption.Timeout = new TimeSpan(0, 0, 60);
                    using (TransactionScope transaction = new TransactionScope(TransactionScopeOption.Required))
                    {
                        try
                        {


                            //dalPractice oDal = new dalPractice();
                            SqlDataAdapter DA = oDal.PracticeUpdateAdapter(nPracticeID);
                            SqlCommandBuilder oBulider = new SqlCommandBuilder(DA);
                            DataSet DS = new DataSet();
                            DA.Fill(DS);

                            if (DS == null) return;

                            DataRow DR = null;

                            string strOldTimes = oDal.PracticeTimeString(nPracticeID);
                            bool isTimesChanged = oDal.CompareTimes(strOldTimes, strTimeCheckValue);

                            bool blAdd = false;
                            if (DS.Tables[0].Rows.Count > 0)
                            {
                                DR = DS.Tables[0].Rows[0];
                                DR.BeginEdit();

                                //修改日志
                                string strLogs = oAdmin.AdminInfo("AdminName") + "(" + oAdmin.AdminID + ")修改:(" + DateTime.Now.ToString("yyyy-MM-dd hh:mm") + "); " +
                                    lg.EditRecord("学员名称", DR["PracticeName"], strPracticeName) +
                                    lg.EditRecord("手机", DR["Mobile"], strMobile) +
                                    lg.EditRecord("固定电话", DR["QQ"], strQQ) +
                                    lg.EditRecord("E-mail", DR["Email"], strEmail) +
                                    //lg.EditRecord("练车日期", DR["PracticeDate"], strPracticeDate) +
                                    //lg.EditRecord("车型", DR["CarNo"], strCarNo) +
                                    lg.EditRecord("教练", DR["CoachName"], strCoachName) +
                                    lg.EditRecord("报考类型", DR["Driver_Type"], strDriverType) +
                                    lg.EditRecord("学员状态", DR["PracticeStatus"], nPracticeStatus) +
                                    lg.EditRecord("确认方式", DR["ConfirmType"], strConfirmType) +
                                    //lg.EditRecord("训练科目", DR["LessonName"], strLessonName) +
                                    lg.EditRecord("备注", DR["Remark"], strRemark);

                                if (!isTimesChanged) strLogs += lg.EditRecord("时间段选择", strOldTimes, strTimeCheckValue);

                                DR["Logs"] = Convert.ToString(DR["Logs"]) + strLogs + Convert.ToChar(13);

                                //strSNO = Convert.ToString(DR["SNO"]);
                                //----------------------------------------------

                                //if (DR["CateID"] != gnCateID){blCateChanged = true
                                // if (not DR["ImgFlag"]){DR["Image"] = strImage
                            }
                            else
                            {
                                blAdd = true;
                                DR = DS.Tables[0].NewRow();
                                DR.BeginEdit();

                                nPracticeID = oAccess.GetMaxID("School_Practice", "PracticeID");      //因为倒数据的导致自动编号错乱,只能用程序方式添加PracticeID了
                                tbPracticeID.Text = nPracticeID.ToString();

                                DR["PracticeID"] = nPracticeID;
                                DR["AdminID"] = oAdmin.AdminID;
                                //   DataTable dtPraStudent = oStudent.StudentInfo(nStudentID);
                                if (dtPraStudent != null && dtPraStudent.Rows.Count > 0)
                                {
                                    DR["UserID"] = Convert.ToString(dtPraStudent.Rows[0]["UserID"]);
                                }
                                DR["AddTime"] = DateTime.Now;
                                //strSNO = Guid.NewGuid().ToString();
                                //DR["SNO"] = strSNO;
                            }

                            DR["StudentID"] = nStudentID;
                            DR["PracticeName"] = strPracticeName;
                            DR["Mobile"] = strMobile;
                            DR["QQ"] = strQQ;
                            DR["Email"] = strEmail;
                            if (lg.IsValidDate(strPracticeDate)) DR["PracticeDate"] = strPracticeDate;
                            DR["Driver_Type"] = strDriverType;
                            DR["CarNo"] = strCarNo;
                            DR["CoachName"] = strCoachName;
                            DR["LessonName"] = strLessonName;
                            DR["ConfirmType"] = strConfirmType;
                            DR["PracticeStatus"] = nPracticeStatus;
                            DR["Remark"] = strRemark;

                            DR.EndEdit();



                            if (DR.RowState == DataRowState.Detached)
                            {
                                //nPracticeID = oAccess.GetMaxID("School_Practice", "PracticeID");  //先获取最新ID,用于跳转到显示页面
                                DS.Tables[0].Rows.Add(DR);
                                DA.Update(DS);
                                // nPracticeID = oAccess.GetMaxID("School_Practice", "PracticeID") - 1;  //为了避免删除后获得的不是最新的id号,等添加了后再重新获取最新id号

                            }
                            else if (DR.RowState == DataRowState.Modified)
                            {
                                //DS.Tables[0].AcceptChanges();
                                DA.Update(DS);
                            }

                        //  System.Transactions.Transaction tr=System.Transactions.Transaction.Current;

                            DS.Dispose();
                            DA.Dispose();
                            oBulider.Dispose();
                            UpdateHadPracticeHours(nStudentID, blAdd, strTimeCheckValue, strOldTimes); //更新预约时长  注意 先更新时长再更新预约时间
                            oDal.PracticeTimeUpdate(nPracticeID, strTimeCheckValue);



                            //发送短信并记录发送结果
                            if (chkMobileSms.Checked)
                            {
                                DataTable dt = oDal.PracticeTimeList(nPracticeID);
                                jx.Models.Mobile.vxSms oSms = new Models.Mobile.vxSms();
                                if (dt != null)
                                {
                                    for (int i = 0; i < dt.Rows.Count; i++)
                                    {
                                        DataRow dr = dt.Rows[i];
                                        string strSms = Str(dr["PracticeName"]) + ",您好!您预约了" + Str(dr["CoachName"]) + "教练于" + Convert.ToDateTime(dr["PracticeDate2"]).ToString("M月d日") + " " + Str(dr["TimeBeg2"]) + "在金盘场地进行练习,请提前半小时到场报到,逾期自误。";
                                        string strSNO = "";
                                        bool Success = oSms.Send("", lg.ToInt(dr["StudentID"]), Str(dr["Mobile"]), strSms, ref strSNO);
                                        oDal.SmsUpdate(nPracticeID, Convert.ToDateTime(GetDate(dr["PracticeDate2"])), Str(dr["TimeBeg2"]), strSNO);
                                    }
                                }
                            }

                            oDal.oAccess.connectionClose();

                            transaction.Complete();

                        }
                        catch (Exception ex)
                        {
                            ScriptManager.RegisterClientScriptBlock(UpdatePanel1, this.GetType(), "", "很抱歉,学员没有预约成功!", true);
                            throw new Exception("发送信息异常,原因:" +ex.Message);

                        }
                        finally
                        {
                            transaction.Dispose();

                        }
                    }
}


但是调试运行时却提示事务超时。我就很郁闷了,难道这个事务要处理的代码太多了就不起作用了吗?  



现在我想问问各位大侠,有谁用过这个TransactionOptions处理事务的,要怎么用,还要注意些什么,还有在什么情况下使用才好,用了后会是程序变慢吗?

现在急需解决,查了很多资料  都是讲基本怎么用,但是没讲会遇到哪些问题,或者遇到了会怎样解决,我都不知道我写了,但到底是不是起到事务的作用了没?  很困惑啊!! c# 事务 c# TransactionOptions 事务 --------------------编程问答-------------------- 我按照上面那样写的话,就会提示:Sys.WebForms.PageRequestManagerServerErrorException: 发送信息异常,原因:Timeout 时间已到。在操作完成之前超时时间已过或服务器未响应。
语句已终止。 --------------------编程问答-------------------- 然后我就把事务的作用范围缩小,代码这样写

          //设置事务范围
                    TransactionOptions transactionOption = new TransactionOptions();
                    //设置事务隔离级别
                    transactionOption.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted; //不可以在事务期间读取可变数据,但是可以修改它
                    //RepeatableRead  可以在事务期间读取可变数据,但是不可以修改。 可以在事务期间添加新数据。
                    // 设置事务超时时间为60秒
                    //  transactionOption.Timeout = new TimeSpan(0, 0, 60);
                    using (TransactionScope transaction = new TransactionScope(TransactionScopeOption.Required))
                    {
                        try
                        {

                            if (DR.RowState == DataRowState.Detached)
                            {
                                //nPracticeID = oAccess.GetMaxID("School_Practice", "PracticeID");  //先获取最新ID,用于跳转到显示页面
                                DS.Tables[0].Rows.Add(DR);
                                DA.Update(DS);
                                // nPracticeID = oAccess.GetMaxID("School_Practice", "PracticeID") - 1;  //为了避免删除后获得的不是最新的id号,等添加了后再重新获取最新id号

                            }
                            else if (DR.RowState == DataRowState.Modified)
                            {
                                //DS.Tables[0].AcceptChanges();
                                DA.Update(DS);
                            }

                        //  System.Transactions.Transaction tr=System.Transactions.Transaction.Current;

                            DS.Dispose();
                            DA.Dispose();
                            oBulider.Dispose();
                            UpdateHadPracticeHours(nStudentID, blAdd, strTimeCheckValue, strOldTimes); //更新预约时长  注意 先更新时长再更新预约时间
                            oDal.PracticeTimeUpdate(nPracticeID, strTimeCheckValue);



                            //发送短信并记录发送结果
                            if (chkMobileSms.Checked)
                            {
                                DataTable dt = oDal.PracticeTimeList(nPracticeID);
                                jx.Models.Mobile.vxSms oSms = new Models.Mobile.vxSms();
                                if (dt != null)
                                {
                                    for (int i = 0; i < dt.Rows.Count; i++)
                                    {
                                        DataRow dr = dt.Rows[i];
                                        string strSms = Str(dr["PracticeName"]) + ",您好!您预约了" + Str(dr["CoachName"]) + "教练于" + Convert.ToDateTime(dr["PracticeDate2"]).ToString("M月d日") + " " + Str(dr["TimeBeg2"]) + "在金盘场地进行练习,请提前半小时到场报到,逾期自误。";
                                        string strSNO = "";
                                        bool Success = oSms.Send("", lg.ToInt(dr["StudentID"]), Str(dr["Mobile"]), strSms, ref strSNO);
                                        oDal.SmsUpdate(nPracticeID, Convert.ToDateTime(GetDate(dr["PracticeDate2"])), Str(dr["TimeBeg2"]), strSNO);
                                    }
                                }
                            }

                            oDal.oAccess.connectionClose();

                            transaction.Complete();

                        }
                        catch (Exception ex)
                        {
                            ScriptManager.RegisterClientScriptBlock(UpdatePanel1, this.GetType(), "", "很抱歉,学员没有预约成功!", true);
                            throw new Exception("发送信息异常,原因:" +ex.Message);

                        }
                        finally
                        {
                            transaction.Dispose();

                        }
                    }


可以执行,但是好像中间执行错误的,还是照样进行下去,并没有回滚。感觉好像并没有执行事务的用法 --------------------编程问答--------------------   为什么没有人啊??  伤心。。。。
补充:.NET技术 ,  ASP.NET
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,