| 
 | 1 | +// <Snippet1>  | 
 | 2 | +using System;  | 
 | 3 | +using System.Transactions;  | 
 | 4 | +using Microsoft.Data.SqlClient;  | 
 | 5 | + | 
 | 6 | +class Program  | 
 | 7 | +{  | 
 | 8 | +    static void Main(string[] args)  | 
 | 9 | +    {  | 
 | 10 | +        string connectionString = "Data Source = localhost; Integrated Security = true; Initial Catalog = AdventureWorks";  | 
 | 11 | + | 
 | 12 | +        string commandText1 = "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong size')";  | 
 | 13 | +        string commandText2 = "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong color')";  | 
 | 14 | + | 
 | 15 | +        int result = CreateTransactionScope(connectionString, connectionString, commandText1, commandText2);  | 
 | 16 | + | 
 | 17 | +        Console.WriteLine("result = " + result);  | 
 | 18 | +    }  | 
 | 19 | + | 
 | 20 | +    static public int CreateTransactionScope(string connectString1, string connectString2,  | 
 | 21 | +                                            string commandText1, string commandText2)  | 
 | 22 | +    {  | 
 | 23 | +        // Initialize the return value to zero and create a StringWriter to display results.    | 
 | 24 | +        int returnValue = 0;  | 
 | 25 | +        System.IO.StringWriter writer = new System.IO.StringWriter();  | 
 | 26 | + | 
 | 27 | +        // Create the TransactionScope in which to execute the commands, guaranteeing    | 
 | 28 | +        // that both commands will commit or roll back as a single unit of work.    | 
 | 29 | +        using (TransactionScope scope = new TransactionScope())  | 
 | 30 | +        {  | 
 | 31 | +            using (SqlConnection connection1 = new SqlConnection(connectString1))  | 
 | 32 | +            {  | 
 | 33 | +                try  | 
 | 34 | +                {  | 
 | 35 | +                    // Opening the connection automatically enlists it in the  | 
 | 36 | +                    // TransactionScope as a lightweight transaction.    | 
 | 37 | +                    connection1.Open();  | 
 | 38 | + | 
 | 39 | +                    // Create the SqlCommand object and execute the first command.    | 
 | 40 | +                    SqlCommand command1 = new SqlCommand(commandText1, connection1);  | 
 | 41 | +                    returnValue = command1.ExecuteNonQuery();  | 
 | 42 | +                    writer.WriteLine("Rows to be affected by command1: {0}", returnValue);  | 
 | 43 | + | 
 | 44 | +                    // if you get here, this means that command1 succeeded. By nesting    | 
 | 45 | +                    // the using block for connection2 inside that of connection1, you    | 
 | 46 | +                    // conserve server and network resources by opening connection2  | 
 | 47 | +                    // only when there is a chance that the transaction can commit.  | 
 | 48 | +                    using (SqlConnection connection2 = new SqlConnection(connectString2))  | 
 | 49 | +                        try  | 
 | 50 | +                        {  | 
 | 51 | +                            // The transaction is promoted to a full distributed    | 
 | 52 | +                            // transaction when connection2 is opened.    | 
 | 53 | +                            connection2.Open();  | 
 | 54 | + | 
 | 55 | +                            // Execute the second command in the second database.    | 
 | 56 | +                            returnValue = 0;  | 
 | 57 | +                            SqlCommand command2 = new SqlCommand(commandText2, connection2);  | 
 | 58 | +                            returnValue = command2.ExecuteNonQuery();  | 
 | 59 | +                            writer.WriteLine("Rows to be affected by command2: {0}", returnValue);  | 
 | 60 | +                        }  | 
 | 61 | +                        catch (Exception ex)  | 
 | 62 | +                        {  | 
 | 63 | +                            // Display information that command2 failed.    | 
 | 64 | +                            writer.WriteLine("returnValue for command2: {0}", returnValue);  | 
 | 65 | +                            writer.WriteLine("Exception Message2: {0}", ex.Message);  | 
 | 66 | +                        }  | 
 | 67 | +                }  | 
 | 68 | +                catch (Exception ex)  | 
 | 69 | +                {  | 
 | 70 | +                    // Display information that command1 failed.    | 
 | 71 | +                    writer.WriteLine("returnValue for command1: {0}", returnValue);  | 
 | 72 | +                    writer.WriteLine("Exception Message1: {0}", ex.Message);  | 
 | 73 | +                }  | 
 | 74 | +            }  | 
 | 75 | + | 
 | 76 | +            // If an exception has been thrown, Complete will not  | 
 | 77 | +            // be called and the transaction is rolled back.    | 
 | 78 | +            scope.Complete();  | 
 | 79 | +        }  | 
 | 80 | + | 
 | 81 | +        // The returnValue is greater than 0 if the transaction committed.    | 
 | 82 | +        if (returnValue > 0)  | 
 | 83 | +        {  | 
 | 84 | +            writer.WriteLine("Transaction was committed.");  | 
 | 85 | +        }  | 
 | 86 | +        else  | 
 | 87 | +        {  | 
 | 88 | +            // You could write additional business logic here, notify the caller by    | 
 | 89 | +            // throwing a TransactionAbortedException, or log the failure.    | 
 | 90 | +            writer.WriteLine("Transaction rolled back.");  | 
 | 91 | +        }  | 
 | 92 | + | 
 | 93 | +        // Display messages.    | 
 | 94 | +        Console.WriteLine(writer.ToString());  | 
 | 95 | + | 
 | 96 | +        return returnValue;  | 
 | 97 | +    }  | 
 | 98 | +}  | 
 | 99 | +// </Snippet1>  | 
0 commit comments