question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Can't Use External Transactions and Retry Strategy with Stored Procedures

See original GitHub issue

With the current way store procedures are wrapped, you can’t include them in an externally defined and managed unit of work. Please refer to “Using Resilient Entity Framework Core Sql Connections and Transactions: Retries with Exponential Backoff”. The article describes how to create an ExecutionStrategy and pass it a delegate as the unit of work to be executed and retries if a transient error occurs. Within the delegate, the transaction is started and committed.

Steps to reproduce

Sorry, I don’t really have steps to reproduce this because it doesn’t seem like it can be done. The core problem is that you need create the ExecutionStrategy on the dbcontext that will be used for the stored procedure. However, this is not exposed in the extensions.

You can sort of hack this in by changing the extensions as shown here: image

DbContextExtensions.txt

Then you can do something like this:

        using var databaseContext = new DeadlocktestContext();
        var strategy = databaseContext.Database.CreateExecutionStrategy();
        await strategy.ExecuteAsync(
            async () =>
            {
                using (var transaction = databaseContext.Database.BeginTransaction())
                {
                    await databaseContext.Procedures.Procedure1Async(1);
                    await transaction.CommitAsync();
                }
            }
        );

However, it seems like a hack or that there should be a better way.

EF Core version in use: EF Core 6.02 Is Handlebars used: no EF Core Power Tools version: 2.5.908.0 Database engine: SQL Server Visual Studio version: Visual Studio 2022

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:11 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
wgm4321commented, Feb 13, 2022

It does solve my issue. Here is what I did:

  • Deleted the generated DbContextExtensions class
  • Changed the reference to DbContextExtensions to:
            var _ = await _context.Set<Procedure1Result>().FromSqlRaw("EXEC @returnValue = [dbo].[Procedure1] @id", sqlParameters).ToListAsync(cancellationToken);
  • Added the entities returned by the stored procedures to a partial class for the context:
        partial void OnModelCreatingPartial(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Procedure1Result>().HasNoKey().ToView(null);
            modelBuilder.Entity<Procedure2Result>().HasNoKey().ToView(null);
        }
  • Then when invoked with the patten below, the retry logic it invoked when a transient error occurs:
    public static async void Task1()
    {
        using var databaseContext = new DeadlocktestContext();
        var strategy = databaseContext.Database.CreateExecutionStrategy();
        await strategy.ExecuteAsync(
            async () =>
            {
                using (var transaction = databaseContext.Database.BeginTransaction())
                {
                    await databaseContext.Procedures.Procedure1Async(1);
                    await transaction.CommitAsync();
                }
            }
        );
    }

Example run: image

This is the entire test code: DeadlockTest.zip

Not sure how you handle closure of issues. Please close this when you feel it should be closed.

0reactions
wgm4321commented, Feb 16, 2022

@ErikEJ I tried the latest build and it looks good ! Thanks.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Working with Transactions - EF6
The new Connection Resiliency feature does not work with user-initiated transactions. For details, see Retrying Execution Strategies.
Read more >
mysql - Unexpected behaviour with InnoDB Transaction retry
1 Answer 1 · The error occurred, so it rolled back the transaction as far as it had gone. · The client code...
Read more >
Should non-idempotent operations be called with a retry ...
My understanding is that I am able to do it because the stored procedures I have are transactional so if they fail, the...
Read more >
Most T-SQL Queries Don't Even Try to Handle Errors.
If you can't count on applications to handle errors, it may be wise to implement error handling in stored procedures in order to...
Read more >
Managing transactions - Amazon Redshift
Manage transactions for stored procedures in Amazon Redshift. ... A call to a stored procedure is treated as a single SQL command. The...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found