步骤 2:跨多个组件扩展事务
目标
在本步骤中,您将了解以下内容:
- 事务流
- 多个对象如何在事务中投票
说明
步骤 1:创建事务组件演示如何编写更新 Microsoft SQL Server Pubs 数据库中的作者信息的简单事务组件。 步骤 2 显示跨多个组件扩展事务时会发生什么情况。
为了符合 COM+ 编程模型,UpdateAuthorAddress
会在完成其工作的过程中调用另一个组件。 第二个组件 ValidateAuthorAddress
会验证作者的地址,并将结果返回给其调用方 UpdateAuthorAddress
。
与其调用方不同,ValidateAuthorAddress
不需要事务,但它仍然可以参与其调用方事务。 在此步骤中,会将其事务属性值设置为 Supported,如下图所示,会将现有事务扩展到新对象。
仅当调用方是事务调用方时,Supported 属性值才会扩展(或流动)现有事务。 UpdateAuthorAddress
调用 ValidateAuthorAddress
时,COM+ 会先查看调用方的上下文,以查看其是否是事务调用方。 接着,COM+ 会查看 ValidateAuthorAddress
上设置的服务属性,并将分配给调用方对象的同一事务标识符分配给新对象。 若要更好地了解此过程,请参阅上下文激活。
由于它们共享相同的事务标识符,因此两个对象必须成功完成其工作,或者 COM+ 中止事务(撤消对 Pubs 数据库所做的任何更改)。
参与事务投票以提交或中止事务的所有对象。 在代码中包含投票指令时,将显式进行投票,如下面的步骤 1 示例代码摘要中所示,此示例代码将创建 UpdateAuthorAddress
组件:
' Everything works.
contextstate.SetMyTransactionVote TxCommit
contextstate.SetDeactivateOnReturn True
Exit Sub
UnexpectedError:
' There's an error.
contextstate.SetMyTransactionVote TxAbort
contextstate.SetDeactivateOnReturn True
投票也会隐式进行,就像在 ValidateAuthorAddress
组件中一样。 除非该对象声明,否则 COM+ 假定对象已成功完成其工作,但尚未准备好停用。 COM+ 假设如下:
contextstate.SetMyTransactionVote TxCommit
contextstate.SetDeactivateOnReturn False
当 ValidateAuthorAddress
返回到其调用方时,COM+ 会将其投票读作提交。 在停用根对象(即事务中的第一个对象,在本例中为 UpdateAuthorAddress
对象)之前,COM+ 不会对投票进行计数。
代码示例
ValidateAuthorAddress
组件会简单检查作者的地址。 由于 UpdateAuthorAddress
未显式投票,COM+ 使用默认投票设置。
Option Explicit
'
' Purpose: This class is used for validating an author's address
' (presumably right before updating that address in the
' database).
'
' Notes: This component could be in a transaction or not; it doesn't
' matter because it doesn't touch any data in a database.
'
Public Function ValidateAuthorAddress( _
ByVal strAddress As String, _
ByVal strCity As String, _
ByVal strState As String, _
ByVal strZip As String) As Boolean
' Default is to validate unless something is found to be wrong.
ValidateAuthorAddress = True
' Invalidate authors who live in New York City
' and authors who live in Montana.
'
If strCity = "New York" And strState = "New York" Then
ValidateAuthorAddress = False
ElseIf strState = "Montana" Then
ValidateAuthorAddress = False
End If
' Done
End Function
总结
将组件的事务属性设置为 Supported 时,可能会导致在调用对象的事务中创建新对象。 COM+ 会查看调用方上下文,以确定新对象的事务状态。 如果调用方是事务调用方,COM+ 会将事务流向新对象。
参与同一事务的所有对象均共享通用事务标识符,COM+ 会从对象的上下文中读取该标识符。
事务中的每个对象都独立于其他对象进行投票。 COM+ 在停用根对象时会对投票进行计数。
可以在提交和中止之间切换对象的事务投票,直到 COM+ 停用对象或 COM+ 停用根对象并结束事务为止。 仅最后一次投票设置计数。 IContextState 和 IObjectContext 接口提供可生成类似投票结果的方法,如下表所示。 可以使用任一接口在事务中显式投票。
IContextState 组合方法 IObjectContext 等效方法 SetMyTransactionVote txVote = TxCommit
SetDeactivateOnReturn bDeactivate = TrueSetComplete SetMyTransactionVote txVote = TxCommit
SetDeactivateOnReturn bDeactivate = FalseEnableCommit SetMyTransactionVote txVote = TxAbort
SetDeactivateOnReturn bDeactivate = TrueSetAbort SetMyTransactionVote txVote = TxAbort
SetDeactivateOnReturn bDeactivate = FalseDisableCommit 除非组件显式投票,否则 COM+ 会将对象的投票设置为等效的 EnableCommit。
显式投票可以减少事务的总体持续时间并释放昂贵的资源锁定。