Using Transactions

Topic Last Modified: 2006-06-12

When you use the server-side Exchange OLE DB (ExOLEDB) provider, you can perform operations on items in a store as a single transaction. To do so, you first create a Microsoft® ActiveX® Data Objects (ADO) Connection object and bind to a particular store. Next, you invoke the _Connection.BeginTrans method. All operations that you subsequently perform within the context of this connection are not committed to the store until the transaction has been committed. To commit the transaction, you invoke the _Connection.CommitTrans method. To cancel the transaction, you invoke the _Connection.RollbackTrans method.

You cannot perform transactions across multiple stores. For example, you cannot create items in two public stores as part of the same transaction.

The following example demonstrates how to perform the following operations, all within the context of a transaction:

  1. Create an application folder and set properties on the folder.
  2. Create a schema subfolder to house schema information for the application.
  3. Create three schema items: one content class definition and two property definitions.
  4. Create a test item in the application folder.

If the transaction is successful, the example then tests the schema information by using the test item created in the application folder. Because none of the operations are actually committed to the store before the transaction has been committed, the schema test operations cannot be performed in the transaction.

Example

VBScript

Note

To access the global schema of an application or a public store, use The ##SCHEMAURI## Macro.

Example

<Job id="createFoldersAndSchemaFolders_Trans">

<reference object="adodb.record"/>

<script language="vbscript">

 option explicit
 Const s    = "urn:schemas-microsoft-com:exch-data:"
 Const dt        = "urn:schemas-microsoft-com:datatypes#"
 Const x   = "urn:schemas-microsoft-com:xml-data#"
 Const cc        = "urn:content-classes:"
 Const d       = "DAV:"
 Const pcc      = "urn:schemas-myorg-tld:content-classes:"
 Const p        = "urn:schemas-myorg-tld:"

 Const vRoot    = "/apps"
 Const appfldr  = "/apps/a2"
 Const pcc_1    = "class1"
 Const pcc_1_fn = "class1_pcc"
 Const pp_1     = "prop1"
 Const pp_1_fn  = "prop1_pp"
 Const pp_2     = "prop2"
 Const pp_2_fn  = "prop2_pp"

 Const test_fn  = "item.txt"

 createFoldersAndSchema_Trans vRoot, appfldr
 createTestItem appfldr & "/" & test_fn
 testSchema1 appfldr & "/" & test_fn
 testSchema2 appfldr


' -- createFolderAndSchema_Trans --
'
' This routine creates the following within a local transaction:
' - an application folder,
' - a schema folder "Schema" (child of app folder)
' - one custom content class definition
' - two custom property definitions (referenced by content class)
' - one test item in app folder with the custom content class
'
'
Sub createFoldersAndSchema_Trans( vRootURL, appfolderURL )

 WScript.Echo ""
 WScript.Echo "-- createFoldersAndSchema_Trans --"

 Dim Rec
 Dim Conn
 Dim info
 Dim infoNT
 Dim URL

 ' Get the fully qualified domain name from the ADSystemInfo object.
 Set info = CreateObject("ADSystemInfo")
 Set InfoNT = CreateObject("WinNTSystemInfo")
 Set Conn = CreateObject("ADODB.Connection")

 URL = "http://" & lcase(infoNT.computername) & _
                   "." & info.domaindnsname & _
                   appfolderURL

 wscript.echo url
 Conn.Provider = "ExOLEDB.DataSource"
 Conn.Open URL

 ' We now have a connection to the appropriate store
 ' Begin transaction
 Dim lvl
 lvl = Conn.BeginTrans

 Set Rec = CreateObject("ADODB.Record")

 ' Try to create the app folder. Use Connection with transaction
 With Rec
   .Open appfolderURL, Conn , adModeReadWrite, adCreateCollection Or adCreateOverwrite
   With .Fields
     .Item(d & "contentclass")             = cc & "folder"
     .Item(s & "schema-collection-ref")       = appfolderURL & "/Schema"
     .Item(s & "expected-content-class").Value    = Array(pcc & pcc_1)         'urn:schemas-myorg-tld:content-classes:class1
     .Update
   End With
   .Close


 ' Now create the folder for the schema items. By convention, this is the "Schema" folder below the App folder
   .Open appfolderURL & "/Schema", Conn, adModeReadWrite, adCreateCollection Or adCreateOverwrite
   With .Fields
     .Item(d & "contentclass").Value            = cc & "folder"
     .Item(s & "expected-content-class").Value  = _
       Array("urn:content-classes:propertydef", "urn:content-classes:contentclassdef","urn:content-classes:item")
     .Item(s & "baseschema").Value              = _
      Array(vRootURL & "/non_ipm_subtree/Schema")
     .Update
   End With
   .Close

   wscript.echo vRootURL & "/non_ipm_subtree/Schema"

  ' Create the first property definition. This property definition has the name
  '  urn:schemas-myorg-tld:prop1
   .Open appfolderURL & "/Schema/" & pp_1_fn, Conn, adModeReadWrite, adCreateNonCollection Or adCreateOverwrite
   With .Fields
     .Item(x  & "name")                 = p & pp_1
     .Item(d  & "contentclass")         = cc & "propertydef"
     .Item(dt & "type")                 = "date"
     .Item(s  & "isindexed")            = False
     .Item(s  & "ismultivalued")        = False
     .Item(s  & "isreadonly")           = False
     .Item(s  & "synchronize")          = False
     .Item(s  & "isrequired")           = False
     .Item(s  & "isvisible")            = True
     .Update
   End With
   .Close

  ' Create the second property definition. This property definition has the name
  '  urn:schemas-myorg-tld:prop2
   .Open appfolderURL & "/Schema/" & pp_2_fn, Conn, adModeReadWrite, adCreateNonCollection Or adCreateOverwrite
   With .Fields
     .Item(x  & "name")                 = p & pp_2
     .Item(d  & "contentclass")         = cc & "propertydef"
     .Item(dt & "type")                 = "string"
     .Item(s  & "isindexed")            = False
     .Item(s  & "ismultivalued")        = False
     .Item(s  & "isreadonly")           = False
     .Item(s  & "synchronize")          = False
     .Item(s  & "isrequired")           = False
     .Item(s  & "isvisible")            = True
     .Update
   End With
   .Close

  ' Create the content class definition. This class has the name
  '  urn:schemas-myorg-tld:content-classes:class1
   .Open appfolderURL & "/Schema/" & pcc_1_fn, Conn, adModeReadWrite, adCreateNonCollection Or adCreateOverwrite
   With .Fields
     .Item(d & "contentclass")                  = cc & "contentclassdef"
     .Item(x & "name")                          = pcc & pcc_1
     .Item(x & "extends").Value                 = Array(cc & "object")
     .Item(x & "element").Value                 = Array(p & pp_1, p & pp_2)
     .Item(s & "closedexpectedcontentclasses")  = False
     .Update
   End With
   .Close

 End with

 If Err.Number <> 0 Then
  wscript.echo "Error!"
  wscript.echo err.number
  wscript.echo err.description
  wscript.echo "Transaction Aborted"
  Conn.RollbackTrans
 Else
  Conn.CommitTrans
  wscript.echo "No Error. Transaction Completed"
 End if


  ' Create a test item. Set its content class to our private class.
  ' When we open this item, the properties we defined for our content class
  ' should appear in Fields collection even though they have not been set.
   Rec.Open appfolderURL & "/" & test_fn, Conn, adModeReadWrite, adCreateNonCollection Or adCreateOverwrite
   With Rec.Fields
     .Item(d & "contentclass") = pcc & pcc_1
     .Item(adDefaultStream).Value.WriteText "Here is the text for the item."
     .Update
   End With

   ' Clean up.
   Conn.Close
   Rec.Close

   Set Conn = Nothing
   Set Rec = Nothing

End Sub

Sub CreateTestItem( itemRelURL )
 Dim Rec
 Dim Conn
 Dim info
 Dim infoNT
 Dim URL

 ' Get the fully qualified domain name from the ADSystemInfo object.
 Set info   = CreateObject("ADSystemInfo")
 Set InfoNT = CreateObject("WinNTSystemInfo")
 Set Conn   = CreateObject("ADODB.Connection")
 Set Rec    = CreateObject("ADODB.Record")

 URL = "http://" & lcase(infoNT.computername) & _
                   "." & info.domaindnsname & _
                   itemRelURL

 wscript.echo url
 Conn.Provider = "ExOLEDB.DataSource"
 Conn.Open URL

  ' Create a test item. Set its content class to our private class.
  ' When we open this item, the properties we defined for our content class
  ' should appear in Fields collection even though they have not been set.
   Rec.Open URL, Conn, adModeReadWrite, adCreateNonCollection Or adCreateOverwrite
   With Rec.Fields
     .Item(d & "contentclass") = pcc & pcc_1
     .Item(adDefaultStream).Value.WriteText "Here is the text for the item."
     .Update
   End With

   ' Clean up.
   Conn.Close
   Rec.Close

   Set Conn = Nothing
   Set Rec = Nothing

End Sub

' -- testSchema1 --
' This routine checks the schema information set using the above routine.
' If the schema scope has been set up properly, the properties
' defined by our custom content class urn:schemas-myord-tld:content-classes:class1
' should appear in the Fields collection for the item even though values have not
' been set for these. If values have been set for these properties, this test
' tells us nothing.
'

Sub testSchema1( Path )

 WScript.Echo ""
 WScript.Echo "-- testSchema1 --"

 Dim Rec
 Set Rec = CreateObject("ADODB.Record")
 Dim Conn
 Set Conn = CreateObject("ADODB.Connection")

 Dim Info
 Set Info = CreateObject("ADSystemInfo")
 Dim InfoNT
 Set InfoNT = CreateObject("WinNTSystemInfo")

 Dim URL
 URL = "http://" & _
   lcase(InfoNT.ComputerName) & "." & _
        Info.DomainDNSName & _
        Path

 Conn.Provider = "ExOLEDB.DataSource"
 Conn.Open URL
 WScript.Echo "Testing schema using item at URL: " & URL
 Rec.Open URL, Conn

 Dim Fld
 For Each Fld in Rec.Fields
   If Fld.Name = (p & pp_1) Then
      WScript.Echo p & pp_1 & " returned in schema!"
   ElseIf Fld.Name = (p & pp_2) Then
      WScript.Echo p & pp_2 & " returned in schema!"
   End If

  ' Clean up.
  Conn.Close
  Rec.Close

  Set Conn = Nothing
  Set Rec = Nothing

End Sub


' -- testSchema2 --
' This routine checks the schema information set using the above routine.
' If the schema scope has been set up properly, the properties
' defined by our custom content class urn:schemas-myord-tld:content-classes:class1
' should appear in the results of a "select *" in the appfolder.
'
Sub testSchema2( path )

 WScript.Echo ""
 WScript.Echo "-- testSchema2 --"

 Dim Conn
 Set Conn = CreateObject("ADODB.Connection")
 Dim Info
 Set Info = CreateObject("ADSystemInfo")
 Dim InfoNT
 Set InfoNT = CreateObject("WinNTSystemInfo")

 Dim URL
 URL = "http://" & _
   infont.computername & "." & _
        info.domaindnsname & "/" & _
        path

 Conn.Provider = "ExOLEDB.DataSource"
 Conn.Open URL

 Dim Rs
 Set Rs = CreateObject("ADODB.Recordset")
 Set Rs.ActiveConnection = Conn
 Rs.Open "select * from """ & path & """"

 Dim Fld
 For Each Fld In Rs.Fields
  If Fld.Name = (p & pp_1) Then
    WScript.Echo p & pp_1 & " returned in schema!"
  ElseIf Fld.Name = (p & pp_2) Then
    WScript.Echo p & pp_2 & " returned in schema!"
  End IF

 ' Clean up.
 Conn.Close
 Rs.Close

 Set Conn = Nothing
 Set Rs = Nothing
End Sub

</script>
</job>