次の方法で共有


手順 3: コンポーネントの再利用

目標

この手順では、次の情報を学習します。

  • 再利用可能なコンポーネント
  • 再利用を計画する方法

説明

この COM+ サービス入門の 2 つの前の部分、 手順 1: トランザクション コンポーネント の作成手順 2: 複数コンポーネント間でのトランザクションの拡張 では、2 つ目のコンポーネントを呼び出して、作業の完了、Microsoft SQL Server Pubs データベースの作成者情報の更新を支援する 1 つのコンポーネントを記述する方法を示します。すべての作業は 1 つのトランザクションによって保護されます。 サンプル コンポーネントでは、作成者のデータを更新し、作成者のアドレスを確認する作業に重点を置き、COM+ はトランザクション処理、 JIT アクティブ化コンカレンシー保護を提供しました。

この手順では、手順 1 と 2 で作成したコンポーネントを再利用する方法を示し、これらのコンポーネントの設計にこれが何を意味するかを確認します。 次の図に示すように、これは新しいコンポーネントの AddNewAuthorを作成することを意味します。これは、 UpdateAuthorAddressを呼び出 して、新しい作成者をデータベースに追加します。

Diagram that shows the flow when reusing components.

既存のコンポーネント機能を再利用するだけでなく、 AddNewAuthorValidateAuthorNameと呼ばれるもう一つの新しいコンポーネントを呼び出します。 上の図に示すように、 ValidateAuthorName 非トランザクションです。 このコンポーネントのトランザクション属性値は、既定の設定 (サポートされていません) のままにして、その処理をトランザクションから除外します。 手順 3 のサンプル コードに示すように、 ValidateAuthorName は、データベースに対して読み取り専用クエリを実行します。このマイナー タスクの失敗によってトランザクションが中止される可能性はありません。 ただし、 AddNewAuthor コンポーネントのトランザクション属性値は [必須] に設定されています。

AddNewAuthorUpdateAuthorAddress、および ValidateAuthorAddress コンポーネントはすべて、トランザクション内で投票します。 このトランザクションでは、 AddNewAuthor は、ルート オブジェクトです。 COM+ は常に、トランザクションで作成された最初のオブジェクトをルート オブジェクトにします。

この例では、 UpdateAuthorAddress コンポーネントの再利用は簡単です。COM+ は、期待されるサービスを自動的に提供します。 ただし、 UpdateAuthorAddress コンポーネントのトランザクション属性値が最初に [必須] ではなく [新規が必要] に設定されている場合、結果は異なります。 サーフェス上では、両方の設定が似ています。両方ともトランザクションを保証します。 ただし、新規が必要は常に新しいトランザクションを開始し、 必須 はオブジェクトの呼び出し元が非トランザクションである場合にのみ新しいトランザクションを開始します。 このことから、 UpdateAuthorAddress を慎重かつ周到に構成することがいかに重要であったかを確認できます。 それ以外の場合、COM+ はサービス要求を異なる方法で解釈し、次の図に示すように、1 つではなく 2 つの関連のないトランザクションを生成している可能性があります。

Diagram that shows the flow when reusing components with

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+ が呼び出されたコンポーネントのサービス要求を解釈する方法に影響します。

手順 1: トランザクション コンポーネントの作成

手順 2: 複数のコンポーネント間でトランザクションを拡張する

トランザクションの構成

スケーラビリティのために設計する