步骤 3:重用组件
目标
在本步骤中,您将了解以下内容:
- 可重复使用的组件。
- 如何计划可重用性。
说明
此 COM+ 服务入门的前两部分(即步骤 1:创建事务组件和步骤 2:跨多个组件扩展事务)演示了如何编写一个组件来调用第二个组件,以便帮助完成某些工作,更新 Microsoft SQL Server Pubs 数据库中的作者信息;所有工作都受单个事务的保护。 示例组件侧重于更新作者数据以及验证作者地址的工作,以及 COM+ 提供的事务处理、JIT 激活和并发保护。
此步骤演示如何重用步骤 1 和 2 中创建的组件,并了解这些组件的设计意味着什么。 如下图所示,这意味着创建新的组件 AddNewAuthor
,以通过调用 UpdateAuthorAddress
将新作者添加到数据库。
除了重用现有组件功能外,AddNewAuthor
还将调用另一个名为 ValidateAuthorName
的新组件。 如上图所示,ValidateAuthorName
是非事务组件。 此组件的事务属性值保留在其默认设置 (Not Supported),以从事务中排除其工作。 如步骤 3 示例代码所示,ValidateAuthorName
会对数据库执行只读查询,此次要任务的失败不可能中止事务。 但是,AddNewAuthor
组件的事务属性值设置为 Required。
AddNewAuthor
、UpdateAuthorAddress
和 ValidateAuthorAddress
组件都在事务中投票。 在此事务中,AddNewAuthor
是根对象。 COM+ 始终将在事务中创建的第一个对象设为根对象。
在此示例中,重用 UpdateAuthorAddress
组件非常简单 - COM+ 会自动提供预期服务。 但是,如果最初将 UpdateAuthorAddress
组件的事务属性值设置为 Requires New,而不是 Required,则结果会有所不同。 在表面上,这两个设置看起来相似;这两者都保证事务。 但是,Requires New 始终启动一个新事务,而 Required 仅在对象的调用方为非事务调用方时才启动新事务。 从中可以看到,仔细和深思熟虑地配置 UpdateAuthorAddress
是多么重要。 否则,COM+ 可能会以不同的方式解释服务请求,从而生成两个不相关的事务(如下图所示),而不是一个。
注意
重复使用组件时,请确保将服务配置为支持所需结果。
示例代码
AddNewAuthor 组件允许对象保持活动状态,直到客户端释放对对象的引用,从而执行新作者的批处理添加。
Option Explicit
'
' Purpose: This class is used for adding a new author.
'
' Notes: IMPT: This component implicitly assumes that it will
' always run in a transaction. Undefined results may
' otherwise occur.
'
' AddNewAuthor
'
Public Sub AddNewAuthor( _
ByVal strAuthorFirstName As String, _
ByVal strAuthorLastName As String, _
ByVal strPhone As String, _
ByVal strAddress As String, _
ByVal strCity As String, _
ByVal strState As String, _
ByVal strZip As String, _
ByVal boolContracted As Boolean)
' Handle any errors.
On Error GoTo UnexpectedError
' Verify component is in a transaction.
' The VerifyInTxn subroutine is described in Step 1.
VerifyInTxn
' Get our object context.
Dim objcontext As COMSVCSLib.ObjectContext
Set objcontext = GetObjectContext
' Get the IContextState object.
Dim contextstate As COMSVCSLib.IContextState
Set contextstate = objcontext
' Validate that the author is OK.
' The ValidateAuthorName function is described after this function.
Dim oValidateAuthName As Object
Dim bValidAuthor As Boolean
Set oValidateAuthName = CreateObject("ComplusPrimer.ValidateAuthorName")
bValidAuthor = oValidateAuthName.ValidateAuthorName( _
strAuthorFirstName, strAuthorLastName)
If Not bValidAuthor Then
Err.Raise 999999, "The AddNewAuthor component", _
"You tried to add an author on the banned list!"
End If
' Open the connection to the database.
Dim conn As ADODB.Connection
Set conn = CreateObject("ADODB.Connection")
' Specify the OLE DB provider.
conn.Provider = "SQLOLEDB"
' Connect using Windows Authentication.
Dim strProv As String
strProv = "Server=MyDBServer;Database=pubs;Trusted_Connection=yes"
' Open the database.
conn.Open strProv
' Tell the database to actually add the author; use empty strings
' for this part and rely on the UpdateAuthorAddress
' component to validate the address/phone/etc data.
' Default Contract flag is off.
Dim strUpdateString As String
strUpdateString = "insert into authors values(_
'789-65-1234'," & _
strAuthorLastName & ", " & _
strAuthorFirstName & ", " & _
"'(555) 555-5555', ', ', ', '98765', "
If boolContracted Then
strUpdateString = strUpdateString + "1)"
Else
strUpdateString = strUpdateString + "0)"
End If
conn.Execute strUpdateString
' Close the connection; this potentially allows
' another component in the same transaction to
' reuse the connection from the connection pool.
conn.Close
Set conn = Nothing
' Create the UpdateAuthorAddress component.
Dim oUpdateAuthAddr As Object
Set oUpdateAuthAddr = CreateObject("ComplusPrimer.UpdateAuthorAddress")
' The component throws an error if anything goes wrong.
oUpdateAuthAddr.UpdateAuthorAddress "", strPhone, _
strAddress, strCity, strState, strZip
Set oUpdateAuthAddr = Nothing
' Everything works--commit the transaction.
contextstate.SetMyTransactionVote TxCommit
' Design issue: Allow batch additions of new
' authors in one transaction, or should each new author be added
' in a single new transaction?
contextstate.SetDeactivateOnReturn False
Exit Sub
UnexpectedError:
' There's an error.
contextstate.SetMyTransactionVote TxAbort
contextstate.SetDeactivateOnReturn True
End Sub
在 AddNewAuthor
将名称添加到数据库之前,ValidateAuthorName
组件会验证作者名称。 如果发生意外情况,此组件会向调用方抛出错误。
Option Explicit
'
' Purpose: This class is used for validating authors before
' adding them to the database.
'
' Notes: This component doesn't need to be in a transaction because
' it is performing read-only queries on the database,
' especially since these queries are not overlapping with
' any updates of end-user data. If an unexpected error
' happens, let the error go back to the caller who
' needs to handle it.
'
Public Function ValidateAuthorName( _
ByVal strAuthorFirstName As String, _
ByVal strAuthorLastName As String _
) As Boolean
ValidateAuthorName = False
' Open the connection to the database.
Dim conn As ADODB.Connection
Set conn = CreateObject("ADODB.Connection")
' Specify the OLE DB provider.
conn.Provider = "SQLOLEDB"
' Connect using Windows Authentication.
Dim strProv As String
strProv = "Server=MyDBServer;Database=pubs;Trusted_Connection=yes"
' Open the database.
conn.Open strProv
' Suppose another hypothetical table has been added to the Pubs
' database, one that contains a list of banned authors.
Dim rs As ADODB.Recordset
Set rs = conn.Execute("select * from banned_authors")
' Loop through the banned-author list looking for the specified
' author.
While Not rs.EOF
If rs.Fields("FirstName") = strAuthorFirstName And _
rs.Fields("LastName") = strAuthorLastName Then
' This is a banned author.
conn.Close
Set conn = Nothing
Set rs = Nothing
Exit Function
End If
rs.MoveNext
Wend
' None of the added authors found in the banned list.
ValidateAuthorName = True
conn.Close
Set conn = Nothing
Set rs = Nothing
End Function
总结
- 有时,不希望组件在事务中投票。
- COM+ 不会对非事务组件强制实施 JIT 激活或并发保护。 可以单独配置这些服务。
- 调用组件的配置会影响 COM+ 如何解释所调用组件的服务请求。
相关主题