Database Connection Resiliency in ASP.NET Core – Part II
In this post, we will see how to implement Database Connection Resiliency in ASP.NET using an execution strategy for Database operation defined using Transaction scope using EFCore in ASP.NET Core.
We already looked at the inbuilt and custom strategy execution pattern using EnableRetry and using a Custom execution strategy.
If interested to see those options, please visit the below article,
Limitation of Retry and Default Execution Strategies
As we understood in our previous articles, RetryOnFailure and custom execution strategies patterns are very useful for retrying defaulted commands automatically in EFCore.
These patterns help in overcoming Transient errors/faults caused due to network connectivity issues or the temporary unavailability of a service, or timeout issues, etc.
When an issue or transient error occurs, resiliency retries all the operations by re-establishing the connection.
Below are a few limitations of Default Execution Strategies,
- Retry /Default Execution Strategies automatically retry all operations on failures.
- Retries all operations without considering data and its state verification managed through operations.
- Default Execution strategies retry all operations defined in the Transaction.
- Any database operation using Transaction scope like Ambient transaction could lead to data corruption.
In such scenarios, one can execute the execution strategy using a delegate which shall create the scope of all the database operation that needs to be performed, etc.
Execution Pattern for Transaction
For transaction below is the execution pattern,
- @1 – Define the execution strategy
- @2- Define Transaction scope for a given context(One can use multi DBContext within a given Trasnacope if needed. Example Ambient Transaction.
- @3 – Define Database resource updates if any.
- @4 – Commit the transaction (for one or multiple DBContext)
The above sample uses the same database schema and scaffolding model entities that we learned in our Getting Started with EFCore in ASP.NET Core article.
For more details, please visit the below post,
Transaction State verification
EF provides an extension method ExecuteInTransaction() to perform state verification of any database operation.
This method, I found this to be very useful for keeping connection resiliency and at the same time keeping track of whether the database operations are successful or not.
Here below is the implementation using the same above methods,
using (var dbcontext = new EmployeeContext())
{
var strategy = dbcontext.Database.CreateExecutionStrategy();
dbcontext.EmployeeDb.Add(new EmployeeDb
{
FirstName = "TheCode",
LastName = "Buzz",
Id="1234"
});
strategy.ExecuteInTransaction(dbcontext,
operation: context =>
{
context.SaveChanges(acceptAllChangesOnSuccess: false);
},
verifySucceeded: context => context.EmployeeDb.AsNoTracking().Any(b => b.Id == "1234"));
dbcontext.ChangeTracker.AcceptAllChanges();
}
In the above code, ‘verifySucceeded‘ is the delegate, that tests whether the operation succeeded even if the exception is thrown while the Transaction was being committed.
Other references :
That’s All, Enjoy Coding !!
Please sound off your comments below if any.
Summary
Connection resiliency is an important aspect of application communication using shared resources (especially in the cloud environment) and such resources are more sensitive to transient faults. Today in this article we touched upon how to manage Database connection resiliency while performing Transaction operations and also learned how to implement an execution strategy for Transaction-based database operation.
Please bookmark this page and share it with your friends. Please Subscribe to the blog to receive notifications on freshly published(2024) best practices and guidelines for software design and development.
Good one .. thanks
Thanks Liza for the feedback. Appreciate it!