定义在操作层的行为TransactionScopeRequired和TransactionAutoComplete在这一章的先前部分描述了。在服务层,有两个额外的行为需要考虑: TransactionIsolationLevel和TransactionTimeout.
TransactionIsolationLevel属性,正如名字所暗示的,影响事务的隔离级别。隔离是指ACID中的I并指导事务如何与其周围环境隔离。有很多隔离级别。Serializable,默认情况下,提供最高级别的隔离并阻止其他部分在事务完成前更新数据。例如,如果事务中包含了一条“select count(*) from orders”语句,没有其他进程可以在事务完成前对orders表插入或者删除任何数据。ReadUncommitted提供了最低级别的隔离,允许任何其他进程在事务完成前对一条事务正在更新的数据进行读取或者写入。在实际应用中,最好是将隔离级别保留成默认值,Serializable,对应的,避免事务锁住非必须的数据,就像select (*) from order 这种情况应该避免。
事务隔离级别在由客户端定义的TransactionScope和由服务行为定义的TransactinIsolationLevel间必须一致。如果没有一个被设置值,按照默认,IsolationLevel.Serializable会被使用。列表5.22显示了客户端和服务端的设置,每个都是ReadUncommitted.
一个事务可能运行的时间也可以被控制。这可以在客户端或者服务端设置,它们的目的不同。在客户端,这可以用来限制一个用户初始化事务操作的运行时间总和。在服务端,这可以由系统管理员设置来确定不可以有更多的事务来使用太多资源。
在列表5.22中,在客户端TransactionScopeOption.Timeout被设置成30秒,意味着用户自定义事务应该在它运行超过30秒钟后推出。也在列表5.22中,在服务端ServiceBehavior, TransactionTimeout被设置成1分钟,意味着如果有任何事务运行超过1分钟,它将自动终止。
列表5.22 设置事务隔离级别和超时时间
// //Client code // TransactionOptions opt = new TransactionOptions(); opt.IsolationLevel = IsolationLevel.ReadUncommitted; opt.Timeout = new TimeSpan(0, 0, 30); using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew, opt)) { localhost1.BankServiceClient proxy = new Client.localhost1.BankServiceClient(); proxy.Transfer("savings", "checking", 100); scope.Complete(); proxy.Close(); }
// //Service code // [ServiceBehavior(TransactionIsolationLevel = IsolationLevel.ReadUncommitted, TransactionTimeout="00:01:00")] public class BankService : IBankService