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