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:
- Create an application folder and set properties on the folder.
- Create a schema subfolder to house schema information for the application.
- Create three schema items: one content class definition and two property definitions.
- 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>