Interceptando comandos - EF Core 3.1

Sonho realizado
- NonQueryExecuted
 - ScalarExecuting
 - ReaderExecuting
 
Vamos ver como isso funciona
public class RalmsInterceptor : DbCommandInterceptor
{
}
Vamos sobrescrever o método ReaderExecuting, isso significa que mesmo antes de enviar o comando para o banco de dados, podemos interceptar e fazer os ajustes que assim for necessário.
public class RalmsInterceptor : DbCommandInterceptor
{
    public override InterceptionResult<DbDataReader> ReaderExecuting(
        DbCommand command, 
        CommandEventData eventData, 
        InterceptionResult<DbDataReader> result)
    {
        //command.CommandText = ...
        return result;
    }
}
Como usar nosso pequeno Interceptador?
1 - Você pode adicionar diretamente em seu DbContext.
public class RalmsContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
            .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFCORE31;Trusted_Connection=True;")
            .AddInterceptors(new RalmsInterceptor());
    }
}
2 - Ou/Em seu Services que basicamente é a mesma coisa
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services
        .AddDbContext<RalmsContext>(p=>p
            .UseSqlServer(@"Server=...")
            .AddInterceptors(new RalmsInterceptor()));
}
Montando um cenário de uso
Sabendo como criar nosso interceptador e como usar, agora vamos pensar em um cenário onde você gostaria de usar o HINT NOLOCK já que isso ainda não é suportado nativamente pelo EF Core, pois bem aqui agente pode fazer um workaround.
public class RalmsInterceptor : DbCommandInterceptor
{
    private static readonly Regex _tableAliasRegex =
        new Regex(@"(?<tableAlias>FROM +(\[.*\]\.)?(\[.*\]) AS (\[.*\])(?! WITH \(NOLOCK\)))",
            RegexOptions.Multiline | 
            RegexOptions.IgnoreCase | 
            RegexOptions.Compiled);
    public override InterceptionResult<DbDataReader> ReaderExecuting(
        DbCommand command,
        CommandEventData eventData,
        InterceptionResult<DbDataReader> result)
    {
        if (!command.CommandText.Contains("WITH (NOLOCK)"))
        {
            command.CommandText =
                _tableAliasRegex.Replace(command.CommandText,
                "${tableAlias} WITH (NOLOCK)");
        }
        return result;
    }
}
Vamos testar?
using System.Linq;
using Microsoft.AspNetCore.Mvc;
namespace Interceptador.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class TestController : ControllerBase
    {
        private readonly RalmsContext _db;
        public TestController(RalmsContext sampleContext)
        {
            _db = sampleContext;
        }
        [HttpGet]
        public IActionResult Get()
        {
            _ = _db.People.Count();
            _ = _db.People.ToList();
            return Ok();
        }
    }
}
Agora veja nossa query
-- _db.People.Count();
SELECT COUNT(*)
FROM [People] AS [p] WITH (NOLOCK)
-- _db.People.ToList();
SELECT [p].[Id], [p].[City], [p].[FirstName], [p].[LastName]
FROM [People] AS [p] WITH (NOLOCK)
Os fontes do exemplo usado está aqui:
https://github.com/ralmsdeveloper/EFCoreInterceptador
#mvpbuzz #mvpbr #mvp #developerssergipe #share #vscode #sqlserver #efcore31 #netcore31 #aspnetcore
      
    
          
          
          
Deixe um comentário