|
| 1 | +Option Explicit On |
| 2 | +Option Strict On |
| 3 | + |
| 4 | +Imports System.Data |
| 5 | +Imports System.Data.SqlClient |
| 6 | +Imports System.Transactions |
| 7 | + |
| 8 | +Module Module1 |
| 9 | + |
| 10 | + Sub Main() |
| 11 | + Dim connectionString1 As String = GetSQLConnectionString1() |
| 12 | + Dim connectionString2 As String = GetSQLConnectionString2() |
| 13 | + Dim string1 As String = "insert into Customers (CustomerID, CompanyName) values ('ZZZZZ', 'ZZZZZ')" |
| 14 | + Dim string2 As String = "insert into Production.UnitMeasure (UnitMeasureCode, Name) values ('ZZZ', 'ZZZ')" |
| 15 | + Dim r As Integer = 0 |
| 16 | + |
| 17 | + Try |
| 18 | + r = CreateTransactionScope(connectionString1, connectionString2, string1, string2) |
| 19 | + Catch ex As Exception |
| 20 | + Console.WriteLine("") |
| 21 | + Console.WriteLine("In calling code: {0}", ex.Message) |
| 22 | + End Try |
| 23 | + Console.WriteLine("return value in caller {0}", r) |
| 24 | + Console.ReadLine() |
| 25 | + End Sub |
| 26 | + |
| 27 | + ' <Snippet1> |
| 28 | + ' This function takes arguments for 2 connection strings and commands to create a transaction |
| 29 | + ' involving two SQL Servers. It returns a value > 0 if the transaction is committed, 0 if the |
| 30 | + ' transaction is rolled back. To test this code, you can connect to two different databases |
| 31 | + ' on the same server by altering the connection string, or to another 3rd party RDBMS |
| 32 | + ' by altering the code in the connection2 code block. |
| 33 | + Public Function CreateTransactionScope( _ |
| 34 | + ByVal connectString1 As String, ByVal connectString2 As String, _ |
| 35 | + ByVal commandText1 As String, ByVal commandText2 As String) As Integer |
| 36 | + |
| 37 | + ' Initialize the return value to zero and create a StringWriter to display results. |
| 38 | + Dim returnValue As Integer = 0 |
| 39 | + Dim writer As System.IO.StringWriter = New System.IO.StringWriter |
| 40 | + |
| 41 | + Try |
| 42 | + ' Create the TransactionScope to execute the commands, guaranteeing |
| 43 | + ' that both commands can commit or roll back as a single unit of work. |
| 44 | + Using scope As New TransactionScope() |
| 45 | + Using connection1 As New SqlConnection(connectString1) |
| 46 | + ' Opening the connection automatically enlists it in the |
| 47 | + ' TransactionScope as a lightweight transaction. |
| 48 | + connection1.Open() |
| 49 | + |
| 50 | + ' Create the SqlCommand object and execute the first command. |
| 51 | + Dim command1 As SqlCommand = New SqlCommand(commandText1, connection1) |
| 52 | + returnValue = command1.ExecuteNonQuery() |
| 53 | + writer.WriteLine("Rows to be affected by command1: {0}", returnValue) |
| 54 | + |
| 55 | + ' If you get here, this means that command1 succeeded. By nesting |
| 56 | + ' the using block for connection2 inside that of connection1, you |
| 57 | + ' conserve server and network resources as connection2 is opened |
| 58 | + ' only when there is a chance that the transaction can commit. |
| 59 | + Using connection2 As New SqlConnection(connectString2) |
| 60 | + ' The transaction is escalated to a full distributed |
| 61 | + ' transaction when connection2 is opened. |
| 62 | + connection2.Open() |
| 63 | + |
| 64 | + ' Execute the second command in the second database. |
| 65 | + returnValue = 0 |
| 66 | + Dim command2 As SqlCommand = New SqlCommand(commandText2, connection2) |
| 67 | + returnValue = command2.ExecuteNonQuery() |
| 68 | + writer.WriteLine("Rows to be affected by command2: {0}", returnValue) |
| 69 | + End Using |
| 70 | + End Using |
| 71 | + |
| 72 | + ' The Complete method commits the transaction. If an exception has been thrown, |
| 73 | + ' Complete is called and the transaction is rolled back. |
| 74 | + scope.Complete() |
| 75 | + End Using |
| 76 | + Catch ex As TransactionAbortedException |
| 77 | + writer.WriteLine("TransactionAbortedException Message: {0}", ex.Message) |
| 78 | + End Try |
| 79 | + |
| 80 | + ' Display messages. |
| 81 | + Console.WriteLine(writer.ToString()) |
| 82 | + |
| 83 | + Return returnValue |
| 84 | + End Function |
| 85 | + ' </Snippet1> |
| 86 | + |
| 87 | + Private Function GetSQLConnectionString1() As String |
| 88 | + ' To avoid storing the connection string in your code, |
| 89 | + ' you can retrieve it from a configuration file. |
| 90 | + Return "Integrated Security=true;database=Northwind;server=(local)" |
| 91 | + End Function |
| 92 | + |
| 93 | + Private Function GetSQLConnectionString2() As String |
| 94 | + ' To avoid storing the connection string in your code, |
| 95 | + ' you can retrieve it from a configuration file. |
| 96 | + Return "Integrated Security=true;database=AdventureWorks;server=(local)" |
| 97 | + End Function |
| 98 | + |
| 99 | +End Module |
| 100 | + |
0 commit comments