Custom Distributed Transaction Management Between Microservices on .Net Core -CTAS

“It’s always the small pieces that make the big picture.”

“All for one and one for all, united we stand divided we fall.”

Alexandre Dumas, The Three Musketeers

Current knowen solutions for distirbuted transaction management:

SAGA SOLUTION (Events/Choreography)
2PC(Two-Phase Commit) SOLUTION

MS SQL DB:

Microtransaction WebApi Service:

dotnet add package Microsoft.EntityFrameworkCore --version 3.1.5
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
dotnet ef dbcontext Scaffold "Server=tcp:192.168.1.7,1433;Database=Deno;User ID=****;Password=****;" Microsoft.EntityFrameworkCore.SqlServer --force -o DB -c DenoContext
public class UserShop
{
public string name { get; set; }
public string surname { get; set; }
public int id { get; set; }
public int no { get; set; }
public string productName { get; set; }
public decimal? productPrice { get; set; }
}
[Route("InsertUser")]
[HttpPost]
public string InsertUser([FromBody] UserShop data)
{
return _userService.InsertUser(data);
}

UserConsumer:

Type = TransactionType.SqlDB

While saving the User data, we set the IsActive property false because of the obey the Consistency of Acid principles. In the next steps, if we met any errors, we don’t have to rollback inserted user data because new user data is saved as a soft delete.

TransactionHistory List is the most important object in this application. We will add all DB Operations to this List. And we will carry it between all microservices. You can think of this List as a DB log files.

userConsumer/Program.cs:

public class TransactionHistory{
public int ID { get; set; }
public string TableName { get; set; }
public TransactionState State { get; set; }
public TransactionStep Step { get; set; }
public TransactionType Type { get; set; }
}
using System.Collections.Generic;
using userConsumer.DB;
public class ProductConsumer : Products
{
public int UserId { get; set; }
public List<TransactionHistory> TransactionList { get; set; }
}
WorkFlow Until User Consumer

ProductConsumer:

Type = TransactionType.SqlDB

We will carry this TransactionHistory List Between Consumers by Using RabbitMQ. Actually, we will log all DB activities on every step and carry it from beginning to end.

using System.Collections.Generic;
using productConsumer.DB;
public class UserDetailQueue : UserDetails
{
public List<TransactionHistory> TransactionList { get; set; }
}
WorkFlow Until Product Consumer

productConsumer/program.cs:

UserDetailConsumer:

SQL PROFILE

userDetailConsumer/Program.cs:

using System.Collections.Generic;
using productConsumer.DB;
public class UserDetailQueue : UserDetails
{
public List<TransactionHistory> TransactionList { get; set; }
}

This is the final work process schema of this application (CTAS):

WorkFlow Of CTAS

Conclusion:

I have been coding since 1993. I am computer and civil engineer. Microsoft MVP. Senior Software Architect. Ride motorcycle. Gamer. Have two daughters.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store