使用自动化事务
自动化事务简化了编程模型,因为它们不需要明确地开始新事务处理过程,或明确执行或取消事务。然而,自动化事务的最大优点是它们能与dtc结合起来,这就使单个事务可以扩展到多个分布式数据源中。在大型分布式应用程序中,这个优点是很重要的。尽管通过手工对dtc直接编程来控制分布式事务是可能的,但自动化事务处理极大的简化了工作量,并且它是为基于组件的系统而设计的。例如,可以方便地以说明方式配置多个组件以执行包含了单个事务处理的任务。
自动化事务依赖于com+提供的分布式事务处理支持特性。结果,只有服务组件(即从servicedcomponent类中派生的组件)能够使用自动化事务。
要为自动化事务处理配置类,操作如下:
从位于enterpriseservices名称空间的servicedcomponent类中派生新类。
通过transaction属性定义类的事务处理需求。来自transactionoption的枚举值决定了如何在com+类中配置类。可与此属性一同设置的其它属性包括事务处理分离等级和超时上限。
为了避免必须明确选出事务处理结果,可以用autocomplete属性对方法进行注释。如果这些方法释放异常,事务将自动取消。注意,如果需要,仍可以直接挑选事务处理结果。更多详情,见本文稍后确定事务处理结果的节。
更多信息
关于com+自动化事务的更多信息,可在平台sdk文档中搜索“通过com+的自动化事务”获取。
关于.ne t事务处理类的示例,见附录中的如何编码.net事务处理。
配置事务处理分离级别
用于com+1.0版--即运行在windows 2000中的com+--的事务处理分离级别被序列化了。这样做提供了最高的分离等级,却是以性能为代价的。系统的整体吞吐量被降低了。因为所涉及到的资源管理器(典型地是数据库)在事务处理期间必须保持读和写锁。在此期间,其它所有事务处理都被阻断了,这种情况将对应用程序的扩展能力产生极大冲击。
随微软windows .net发行的com+ 1.5版允许有com+目录中按组件配置事务处理分离等级。与事务中根组件相关的设置决定了事务处理的分离等级。另外,同一事务流中的内部子组件拥有的事务处理等级必须不能高于要组件所定义的等级。如果不是这样,当子组件实例化时,将导致错误。
对.net管理类,transaction属性支持所有的公有isolation属性。你可以用此属性陈述式地指定一特殊分离等级,如下面的代码所示:
[transaction(transactionoption.supported, isolation=transactionisolationlevel.readcommitted)]
public class account : servicedcomponent
{
. . .
}
更多信息
关于配置事务处理分离等级及其它windows .net com+增强特性的更多信息,见msdn杂志2001年8月期的“windows xp:利用com+ 1.5的增强特性使你的组件更强壮”一文。
确定事务处理结果
在单个事务流的所有事务处理组件上下文中,自动化事务处理结果由事务取消标志和一致性标志的状态决定。当事务流中的根组件成为非活动状态(并且控制权返回调用者)时,确定事务处理结果。这种情况在图5中得到了演示,此图显示的是一个典型的银行基金传送事务。
图5 事务流上下文
当根对象(在本例中是对象)变为非活动状态,并且客户的方法调用返回时,确定事务处理结果。在任何上下文中的任何一致性标志被设为假,或如果事务处理取消标志设为真,那么底层的物理dtc事务将被取消。
可以以下面两种方式之一从.net对象中控制事务处理结果:
可以用autocomplete属性对方法进行注释,并让.net自动存放将决定事务处理结果投票。如果方法释放异常,利用此属性,一致性标志自动地被设为假(此值最终使事务取消)。如果方法返回而没有释放异常,那么一致性标志将设为真,此值指出组件乐于执行事务。这并没有得到保证,因为它依赖于同一事务流中其它对象的投票。
可以调用contextutil类的静态方法setcomplete或 setabort,这些方法分别将一致性标志设为真或假。
严重性大于10的sql server错误将导致管理数据供应器释放sqlexception类型的异常。如果方法缓存并处理异常,就要确保或者通过手工取消了事务,或者方法被标记了[autocomplete],以保证异常能传递回调用者。
autocomplete方法
对于标记了属性的方法,执行下面操作:
将sqlexception传递加调用堆栈。
将sqlexception封装在外部例外中,并传递回调用者。也可以将异常封装在对调用者更有意义的异常类型中。
异常如果不能传递,将导致对象不会提出取消事务,从而忽视数据库错误。这意味着共享同一事务流的其它对象的成功操作将被提交。
下面的代码缓存了sqlexception,然后将它直接传递回调用者。事务处理最终将被取消,因为对象的一致性标志在对象变为非活动状态时自动被设为假。
[autocomplete]
void somemethod()
{
try
{
// open the connection, and perform database operation
. . .
}
catch (sqlexception sqlex )
{
logexception( sqlex ); // log the exception details
throw; // rethrow the exception, causing the consistent
// flag to be set to false.
}
finally
{
// close the database connection
. . .
}
}
non-autocomlete方法
对于没有autocomplete的属性的方法,必须:
在catch块内调用contextutil.setabort以终止事务处理。这就将相容标志设置为假。
如果没有发生异常事件,调用contextutil.setcomplete,以提交事务,这就将相容标志设置为真(缺省状态)。
代码说明了这种方法。
void someothermethod()
{
try
{
// open the connection, and perform database operation
. . .
contextutil.setcomplete(); // manually vote to commit the transaction
}
catch (sqlexception sqlex)
{
logexception( sqlex ); // log the exception details
contextutil.setabort(); // manually vote to abort the transaction
// exception is handled at this point and is not propagated to the caller
}
finally
{
// close the database connection
. . .
}
}
注意 如果有多个catch块,在方法开始的时候调用contextvtil.setabort,以及在try块的末尾调用contextutil.setcomplete都会变得容易。用这种方法,就不需要在每个catch块中重复调用contextutil.setabort。通过这种方法确定的相容标志的设置只在方法返回时有效。
对于异常事件(或循环异常),必须把它传递到调用堆栈中,因为这使得调用代码认为事务处理失败。它允许调用代码做出优化选择。比如,在银行资金转账中,如果债务操作失败,则转帐分支可以决定不执行债务操作。
如果把相容标志设置为假并且在返回时没有出现异常事件,则调用代码就没有办法知道事务处理是否一定失败。虽然可以返回boolean值或设置boolean输出参数,但还是应该前后一致,通过显示异常事件以表明有错误发生。这样代码就有一种标准的错误处理方法,因此更简明、更具有相容性。
数据分页
在分布式应用程序中利用数据进行分页是一项普遍的要求。比如,用户可能得到书的列表而该列表又不能够一次完全显示,用户就需要在数据上执行一些熟悉的操作,比如浏览下一页或上一页的数据,或者跳到列表的第一页或最后一页。
这部分内容将讨论实现这种功能的选项,以及每种选项在性能和缩放性上的效果。
选项比较
数据分页的选项有:
利用sqldataadapter的fill方法,将来自查询处的结果填充到dataset中。
通过com的可相互操作性使用ado,并利用服务器光标。
利用存储的过程手工实现数据分页。
对数据进行分页的最优选项依赖于下列因素:
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器