asp.net 事务的处理,dts 的设置,asp.net三种事务处理方法,三层架构,微软企业库,动软生成器生成的代码下如何使用事务

在上一篇文章中,由于我需要同时往 订单表和订单详情表插入数据(订单详情表里面的订单编号是订单表的id主键自动生成的值),由于牛腩购物网是用动软生成器,微软企业库的三层架构,在DAL层已经封装好了代码,所以我用到的是   TransactionScope 来实现的事务处理。

 

1:  dts的设置   在运行里面输入   dcomcnfg

在.NET中使用TransactionScope进行事务控制时,必须设置客户端和服务器端的MSDTC安全配置如下:否则只能在数据库服务器上可以正常使用,客户端使用会报错“事务已被隐式或显式提交,或已终止。 ”。

image

然后在我们的项目上,先添加引用 ,并在代码中 using System.Transactions;

image

 
最后,我贴出我的代码。
我先通过 int orderid = orderdao.Add(order);  来获取订单表自动生成的ID,并且接下来,我循环购物车,把购物车里面的商品,添加到 订单详情表里面
最后我scope.Complete();   这样就提交了事务,由于我的事务是放在 using里面的,所以会自动释放我用到的事务,主要代码都是放在try里面的,如果报错,那么位于
using里面的 事务范围,就会回滚,不执行操作。(我刚开始没有设置DTS,也报错了,也回滚了)
 
//开始插入到两张表,用到事务。需要在项目上添加引用 System.Transactions ,而且还需要写 using System.Transactions;
            using (TransactionScope scope = new TransactionScope())  //这里有创建一个  TransactionScope 表示事务性代码,因为用到using会自动释放
            {
                try
                {
                    //如果这里报错的话,整个scope 都会自动 回滚的
                    int orderid = orderdao.Add(order);
                    if (orderid > 0)
                    {
                        DAL.OrderdetailsDAO oddao = new DAL.OrderdetailsDAO();
                        foreach (Model.ShopItem item in sc.GetItemList())
                        {
                            oddao.Add(new Model.Orderdetails {  //这里是添加订单详情表
                            orderid=orderid,
                            price=item.price,
                            proid=item.proid,
                            quantity=item.quantity
                            });
                        }
                        scope.Complete();
                    }
                    else
                    {
                        Utility.Tool.alert("订单添加失败,请联系管理员", this.Page);
                    }
                    
                }
                catch (Exception re)
                {
                    Response.Write("事务错误,具体报错信息是:"+re.Message);
                    Response.End();
                }
            }

 

知识点:  asp.net三种事务处理

三层结构下,数据访问层与业务逻辑分离。从对象关系角度看,业务逻辑层的对象依赖于数据访问层。.net平台提供了ado.net对数据库进行操作,connection对象提供了对database连接与transaction的功能。在分层结构下,数据访问层处理了对数据库的操作,实现了domain每一个对象与database的方法。例如对象Customer,提供CustomerDAO.Add(),CustomerDAO.Update()等等的方法,每一个方法都会引用独立的connection对象。业务层直接调用CustomerDAO的方法。connection对象对业务层是close状态,业务层不能访问到并且控制ado.net提供的transaction。在不破坏分层体系结构前提下一般有三种方式来实现。

 

SQL事务处理ADO.NET事务处理COM+事务处理(也就是文章开头的 TransactionScope )

 

SQL事务处理:  SqlTransaction

应用程序通过在 SqlConnection 对象上调用 BeginTransaction 来创建 SqlTransaction 对象。对 SqlTransaction 对象执行与该事务关联的所有后续操作(例如提交或中止该事务)。

你可以写在sql里面,例如你写一个存储过程,在插入订单表的时候,也同时插入订单详情表

SQL 脚本使用 BEGIN TRANSACTION、COMMIT TRANSACTION、COMMIT WORK、ROLLBACK TRANSACTION 或 ROLLBACK WORK Transact-SQL 语句定义显式事务。

BEGIN TRANSACTION

标记显式连接事务的起始点。

COMMIT TRANSACTION 或 COMMIT WORK

如果没有遇到错误,可使用该语句成功地结束事务。该事务中的所有数据修改在数据库中都将永久有效。事务占用的资源将被释放。

ROLLBACK TRANSACTION 或 ROLLBACK WORK

用来清除遇到错误的事务。该事务修改的所有数据都返回到事务开始时的状态。事务占用的资源将被释放。

 

 

 

 

 

ADO.NET事务处理:

在 ADO.NET SqlClient 托管提供程序中,对 SqlConnection 对象使用 BeginTransaction 方法可以启动一个显式事务。若要结束事务,可以对 SqlTransaction 对象调用 Commit()Rollback() 方法


public
void ExecuteNoneSql(string p_sqlstr, params string[] p_cmdStr) { using (SqlConnection conn = new SqlConnection(p_sqlstr)) { Conn.Open(); SqlCommand cmd = new SqlCommand(); cmd.Connection = conn; SqlTransaction trans = null; trans = conn.BeginTransaction(); //初始化事务 cmd.Transaction = trans; //绑定事务 try { for (int i = 0; i < p_cmdStr.Length; i++) { cmd.CommandText = p_cmdStr[i]; cmd.CommandType = CommandType.Text; cmd.ExecuteNonQuery(); } trans.Commit(); //提交 } catch (SqlException e) { if (trans != null) trans.Rollback(); //回滚 else {//写日志} } } }

带保存点回滚示例:


using
(SqlConnection conn = new SqlConnection(p_sqlstr)) { conn.Open(); SqlCommand cmd = new SqlCommand(); cmd.Connection = conn; SqlTransaction trans = conn.BeginTransaction("table"); cmd.Transaction = trans; try { cmd.CommandText = "Insert into table_name1 values(values1,values2,....)"; cmd.CommandType = CommandType.Text; cmd.ExecuteNonQuery(); cmd.CommandText = "Insert into table_name2 values(values1,values2,....)"; cmd.CommandType = CommandType.Text; cmd.ExecuteNonQuery(); trans.Save("table1"); cmd.CommandText = "Insert into table_name2 values(values1,values2,....)"; cmd.CommandType = CommandType.Text; cmd.ExecuteNonQuery(); trans.Save("table2"); trans.Commit(); } catch { try { trans.Rollback("table2") ; } catch { try{ trans.Rollback("table1") ; } catch{ trans.Rollback("table") ; } } } }

 

三者性能比较:

性能排名: SQL事务处理>ADO.NET事务处理>COM+事务处理(TransactionScope )

SQL事务处理只需要进行一次数据库交互,优点就是速度很快,而且所有逻辑包含在一个单独的调用中,与应用程序独立,缺点就是与数据库绑定。

ADO.NET需要2n次数据库往返,但相对而言,ADO.NET事务处理性能比SQL事务处理低很少,在一般应用程序中可以忽略。而且ADO.NET事务处理将事务处理与数据库独立,增加了程序的移植性。而且他也可以横跨多个数据库,不过他对于数据库的类型要求一致。

COM+事务处理性能最低,主要因为COM+本身的一些组件需要内存开销。但COM+可以横跨各种数据存储文件,这一点功能是前两者所无法媲美的。

 

 

另外:如果是asp的话,还可以在 OLE DB 中使用显式事务。调用 ITransactionLocal::StartTransaction 方法可启动事务。如果将 fRetaining 设置为 FALSE,通过调用 ITransaction::CommitITransaction::Abort 方法结束事务时不会自动启动另一事务。

在 ADO 中,对 Connection 对象使用 BeginTrans 方法可启动隐式事务。若要结束该事务,可调用该 Connection 对象的 CommitTransRollbackTrans 方法。(这个也就是上面的asp的事务的方法)

在asp的时候,就用到过事务,但是这个事务是和一个 connection 链接对象在一起的

<%
'asp事务处理。
'测试数据库为sql server,服务器为本机,数据库名为test,表名为a,两个字段id(int)主键标识,num(int)
set conn=server.CreateObject("adodb.connection") 
strConn="provider=sqloledb.1;persist security info=false;uid=sa;pwd=sa;Initial Catalog=test;Data Source=."
conn.Open strConn
'以上代码建立数据库连接
conn.BeginTrans '事务开始
strSql1="update a set num=1000 where id=24" '第一个sql语句为update。(语法正确)
strSql2="insert into a(num) values('a')" '第二个sql语句为错误的sql语句
strSql3="insert into a(num) values(33333)" '第三个sql语句为正确的sql语句 


call conn.execute(strSql1)  
call conn.execute(strSql2)  
call conn.execute(strSql3)  


if conn.Errors.Count=0 then  
      conn.CommitTrans  '如果没有conn错误,则执行事务提交
else 
      conn.RollbackTrans '否则回滚
end if
%>
posted @ 2012-04-18 18:06  asp_net老友记  阅读(999)  评论(0编辑  收藏  举报