Wednesday, March 8, 2023

Entity Framework Core and Connection Resiliency

In this post, let's see some built-in features in EF Core that supports Connection Resiliency. For example, if the connection to the database dropped while executing a command, we might need to retry the operation. While we can write the code to do it ourselves, EF Core out of the box supports retry using execution strategies.

The execution strategy can be configured in the following ways.

When configuring the options for your context:

public class MyDbContext : DbContext
{
    public DbSet<Customer> Customers { getset; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
            .UseSqlServer(
                @"Server=(localdb)\mssqllocaldb;Database=EfCore8;Trusted_Connection=True",
                providerOptions =>
                {
                    providerOptions.EnableRetryOnFailure();
                }
            );
    }
}

In the Program.cs or Startup.cs for an ASP.NET Core application:

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MyDbContext>(options =>
{
    options.UseSqlServer(
        @"Server=(localdb)\mssqllocaldb;Database=EfCore8;Trusted_Connection=True",
        providerOptions =>
        {
            providerOptions.EnableRetryOnFailure();
        });
});

or

public void ConfigureServices(IServiceCollection services)
{
    // some code

    services.AddDbContext<MyDbContext>(options =>
    {
        options.UseSqlServer(
            @"Server=(localdb)\mssqllocaldb;Database=EfCore8;Trusted_Connection=True",
            providerOptions =>
            {
                providerOptions.EnableRetryOnFailure();
            });
    });
}

If you wish to change the defaults of the execution strategy, you can do that by implementing the abstract class ExecutionStrategy.

using Microsoft.EntityFrameworkCore.Storage;

internal class CustomExecutionStrategy : ExecutionStrategy
{
    public CustomExecutionStrategy(ExecutionStrategyDependencies dependenciesint maxRetryCount, TimeSpan maxRetryDelay)         : base(dependencies, maxRetryCount, maxRetryDelay) { }

    protected override bool ShouldRetryOn(Exception exception)
    {
        // your custom logic here

        return true;
    }
}

And register the CustomExecutionStrategy.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
        .UseSqlServer(
            @"Server=(localdb)\mssqllocaldb;Database=EfCore8;Trusted_Connection=True",
            providerOptions =>
            {
                var maxRetryCount = 5;
                var maxRetryDelay = TimeSpan.FromSeconds(10);

                providerOptions.ExecutionStrategy(dependencies => new CustomExecutionStrategy(dependencies, maxRetryCount, maxRetryDelay));
            }
        );
}

You can even register your own execution strategy by implementing IExecutionStrategy something like below.

using Microsoft.EntityFrameworkCore.Storage;

internal class CustomExecutionStrategy : IExecutionStrategy
{
    private readonly ExecutionStrategyDependencies _dependencies;

    public CustomExecutionStrategy(ExecutionStrategyDependencies dependencies)
    {
        _dependencies = dependencies;
    }

    // interface implementation
}

Hope this helps.

Read More,
   Connection Resiliency

Happy Coding.

Regards,
Jaliya

No comments:

Post a Comment