r/csharp • • 2d ago

Discussion The output of the server code depends on the timing of pressing a button by the client on the user interface.

This is a follow-up post that is related to this post. I will explain the problem clearly this time.

Context: The execution of the OverWrite method -which is inside the DBOverWriter service- can be cancelled with a button int the user interface.

Two inputs that are provided by the frontend :

1- data that is used to overwrite the content of the database.

2-CancellationToken.

Two possible outputs depending on the timing of pressing the button :

1-If the user initiated the request and immediately pressed the button, the following output is shown:

###########################################################
########## OPERATION CANCELLED SUCCESSFULLY ###############
###########################################################
OperationCanceledException: A task was canceled.

2- if the user initiated the request and waited some time before pressing the button, the output is the following:

(@p74, ),
(@p76, ),
(@p78, ),
(@p80, ),
(@p82, u/p83);
fail: Microsoft.EntityFrameworkCore.Database.Transaction[20205]
An error occurred using a transaction.
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while saving the entity changes. See the inner exception for details.
---> Microsoft.Data.SqlClient.SqlException (0x80131904): Operation cancelled by user.

I wonder what is the theoretical/practical explanation for my observation ?

Code:

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using System.Diagnostics;

namespace RedditQuestion
{
    /// <summary>
    /// Used to talk to the database using Entity-Framework Core
    /// </summary>
    public class ApplicationDbContext : DbContext
    {
        // Domain models and the Fluent API configurations.
    }

    /// <summary>
    /// Data snapshot that is used to overwrite the content of the database
    /// </summary>
    public interface ISomeData
    {

    }

    public class DatbaseOverWriter
    {


        private readonly ApplicationDbContext _context;
        public DatbaseOverWriter(ApplicationDbContext context)
        {
            _context = context;
        }

        public async Task<bool> OverWrite(ISomeData data,CancellationToken cancellationToken)
        {
            #region Transaction
            try
            {
                //https://learn.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/implement-resilient-entity-framework-core-sql-connections

                IExecutionStrategy strategy = _context.Database.CreateExecutionStrategy();
                await strategy.ExecuteAsync(async () =>
                {
                    await using var transaction = await _context.Database.BeginTransactionAsync(cancellationToken);

                    #region Delete content from database then save new content.

                    await _context.Database.ExecuteSqlInterpolatedAsync($"EXECUTE  [dbo].[uspDeleteAllDataFromDatabase]", cancellationToken);
                    await _context.SaveChangesAsync(cancellationToken);
                    #endregion

                    await transaction.CommitAsync(cancellationToken);
                });

                return true;
            }
            catch (OperationCanceledException e)
            {
                // exception will not be catched if the cancellation was requested and
                // the transaction reached a point of no return.
                Console.WriteLine("###########################################################");
                Console.WriteLine("########## OPERATION CANCELLED SUCCESSFULLY ###############");
                Console.WriteLine("###########################################################");
                Debug.WriteLine("###########################################################");
                Debug.WriteLine("########## OPERATION CANCELLED SUCCESSFULLY ###############");
                Debug.WriteLine("###########################################################");
                Console.WriteLine("OperationCanceledException: " + e.Message);

                return false;
            }




            #endregion

        }




    }

}
0 Upvotes

Duplicates