步骤 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+ 停用根对象并结束事务为止。 仅最后一次投票设置计数。 IContextStateIObjectContext 接口提供可生成类似投票结果的方法,如下表所示。 可以使用任一接口在事务中显式投票。

    IContextState 组合方法 IObjectContext 等效方法
    SetMyTransactionVote txVote = TxCommit
    SetDeactivateOnReturn bDeactivate = True
    SetComplete
    SetMyTransactionVote txVote = TxCommit
    SetDeactivateOnReturn bDeactivate = False
    EnableCommit
    SetMyTransactionVote txVote = TxAbort
    SetDeactivateOnReturn bDeactivate = True
    SetAbort
    SetMyTransactionVote txVote = TxAbort
    SetDeactivateOnReturn bDeactivate = False
    DisableCommit
  • 除非组件显式投票,否则 COM+ 会将对象的投票设置为等效的 EnableCommit

  • 显式投票可以减少事务的总体持续时间并释放昂贵的资源锁定。

步骤 1:创建事务组件

步骤 3:重用组件

上下文激活

在 COM+ 中管理自动事务