public static void Execute() { var id = new Random().Next(0, 1000).ToString(CultureInfo.InvariantCulture); using (var scope = new TransactionScope()) { // cross app domain call using (var client = new HttpClient()) { using (var request = new HttpRequestMessage(HttpMethod.Post, String.Format(ConfigurationManager.AppSettings["urlPost"], id))) { // forward transaction token request.AddTransactionPropagationToken(); var response = client.SendAsync(request).Result; response.EnsureSuccessStatusCode(); } } // insert data in local database using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["connectionStringClient"].ConnectionString)) { connection.Open(); using (var command = new SqlCommand(String.Format("INSERT INTO [Table_A] ([Name], [CreatedOn]) VALUES ('{0}', GETDATE())", id), connection)) { command.ExecuteNonQuery(); } } // Commit client and server operation scope.Complete(); } }
static void Main(string[] args) { while (true) { Console.WriteLine("Press a Key to start the Transaction"); Console.ReadLine(); using (var scope = new TransactionScope()) { bool commit = true; try { for (int i = 0; i < 2; i++) { // database operation done in an external app domain using (var client = new HttpClient()) { client.BaseAddress = new Uri(@"http://*****:*****@"http://localhost:5000"); .Net core(not working... for now...) //https://github.com/dotnet/runtime/issues/715 using (var request = new HttpRequestMessage(HttpMethod.Post, "work/dojob")) { request.Content = new StringContent("\"client\"", System.Text.Encoding.UTF8, "application/json"); //Uncomment to simulate an error! //request.Content = new StringContent("\"error\"", System.Text.Encoding.UTF8, "application/json"); // forward transaction token var token = request.AddTransactionPropagationToken(); Console.WriteLine($"{token}::>>{i}..."); var response = client.SendAsync(request).Result; response.EnsureSuccessStatusCode(); Console.WriteLine($"{i}:OK!"); } } Console.WriteLine($"5 sec delay..."); System.Threading.Thread.Sleep(5000); } } catch (Exception ex) { commit = false; Console.WriteLine(ex.ToString()); } if (commit) { Console.WriteLine("Press Enter to Commit! (You might use the transaciton IT to make request from another client such as postman)"); Console.ReadLine(); // Commit local and cross domain operations scope.Complete(); Console.WriteLine("C O M M I T E D"); } else { Console.WriteLine("Rolling Back!!!!!"); } } } }
public static void Execute() { using (var scope = new TransactionScope()) { var id = new Random().Next(0, 1000).ToString(CultureInfo.InvariantCulture); // cross app domain call using (var client = new HttpClient()) { using (var request = new HttpRequestMessage(HttpMethod.Post, String.Format(ConfigurationManager.AppSettings["urlPost"], id))) { // forward transaction token request.AddTransactionPropagationToken(); var response = client.SendAsync(request).Result; response.EnsureSuccessStatusCode(); } // Here we are sending the same Id. Because this field is a unique primary key, the DB throw an exception // Using the HttpResponseMessage.EnsureSuccessStatusCode() we check if the HTTP response status code is 200. // If is not, the EnsureSuccessStatusCode() method thor an exception, forcing the execution to get out from the using // scope without invoking the Complete() method ending up with a server and client rollback. using (var request = new HttpRequestMessage(HttpMethod.Post, String.Format(ConfigurationManager.AppSettings["urlPost"], id))) { // forward transaction token request.AddTransactionPropagationToken(); var response = client.SendAsync(request).Result; response.EnsureSuccessStatusCode(); } } // insert data in local database using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["connectionStringClient"].ConnectionString)) { connection.Open(); using (var command = new SqlCommand(String.Format("INSERT INTO [Table_A] ([Name], [CreatedOn]) VALUES ('{0}', GETDATE())", id), connection)) { command.ExecuteNonQuery(); } } scope.Complete(); } }