手順 3: コンポーネントの再利用
目標
この手順では、次の情報を学習します。
- 再利用可能なコンポーネント
- 再利用を計画する方法
説明
この COM+ サービス入門の 2 つの前の部分、 手順 1: トランザクション コンポーネント の作成 と 手順 2: 複数コンポーネント間でのトランザクションの拡張 では、2 つ目のコンポーネントを呼び出して、作業の完了、Microsoft SQL Server Pubs データベースの作成者情報の更新を支援する 1 つのコンポーネントを記述する方法を示します。すべての作業は 1 つのトランザクションによって保護されます。 サンプル コンポーネントでは、作成者のデータを更新し、作成者のアドレスを確認する作業に重点を置き、COM+ はトランザクション処理、 JIT アクティブ化、 コンカレンシー保護を提供しました。
この手順では、手順 1 と 2 で作成したコンポーネントを再利用する方法を示し、これらのコンポーネントの設計にこれが何を意味するかを確認します。 次の図に示すように、これは新しいコンポーネントの AddNewAuthor
を作成することを意味します。これは、 UpdateAuthorAddress
を呼び出 して、新しい作成者をデータベースに追加します。
既存のコンポーネント機能を再利用するだけでなく、 AddNewAuthor
は ValidateAuthorName
と呼ばれるもう一つの新しいコンポーネントを呼び出します。 上の図に示すように、 ValidateAuthorName
非トランザクションです。 このコンポーネントのトランザクション属性値は、既定の設定 (サポートされていません) のままにして、その処理をトランザクションから除外します。 手順 3 のサンプル コードに示すように、 ValidateAuthorName
は、データベースに対して読み取り専用クエリを実行します。このマイナー タスクの失敗によってトランザクションが中止される可能性はありません。 ただし、 AddNewAuthor
コンポーネントのトランザクション属性値は [必須] に設定されています。
AddNewAuthor
、 UpdateAuthorAddress
、および ValidateAuthorAddress
コンポーネントはすべて、トランザクション内で投票します。 このトランザクションでは、 AddNewAuthor
は、ルート オブジェクトです。 COM+ は常に、トランザクションで作成された最初のオブジェクトをルート オブジェクトにします。
この例では、 UpdateAuthorAddress
コンポーネントの再利用は簡単です。COM+ は、期待されるサービスを自動的に提供します。 ただし、 UpdateAuthorAddress
コンポーネントのトランザクション属性値が最初に [必須] ではなく [新規が必要] に設定されている場合、結果は異なります。 サーフェス上では、両方の設定が似ています。両方ともトランザクションを保証します。 ただし、新規が必要は常に新しいトランザクションを開始し、 必須 はオブジェクトの呼び出し元が非トランザクションである場合にのみ新しいトランザクションを開始します。 このことから、 UpdateAuthorAddress
を慎重かつ周到に構成することがいかに重要であったかを確認できます。 それ以外の場合、COM+ はサービス要求を異なる方法で解釈し、次の図に示すように、1 つではなく 2 つの関連のないトランザクションを生成している可能性があります。
Note
コンポーネントを再利用する場合は、目的の結果をサポートするようにサービスが構成されていることを確認します。
サンプル コード
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
ValidateAuthorName
コンポーネントは 、 AddNewAuthor
がデータベースに名前を追加する前に 作成者名を検証します。 予期しない事態が発生した場合、このコンポーネントは呼び出し元にエラーをスローします。
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+ が呼び出されたコンポーネントのサービス要求を解釈する方法に影響します。
関連トピック