EF Core拦截器获取或修改SQL语句

EF Core拦截器获取或修改SQL语句

最近在看EF Core官方文档时,发现有个叫拦截器的东西,那么这个拦截器有啥用呢?其实,一般情况下,我们可能也有用不到它。当我们需要操作EF Core执行的SQL语句或者操作数据库时,那么,拦截器就派上用场了。

在开始之前,我们先来认识三个拦截器接口

接口名 用途 基类
IDbCommandInterceptor 创建命令、执行命令、命令失败、释放命令的 DbDataReader DbCommandInterceptor
IDbConnectionInterceptor 打开、关闭连接、连接失败 DbConnectionInterceptor
IDbTransactionInterceptor 创建事务、使用现有事务、提交事务、回滚事务、创建和使用保存点、事务失败 DbTransactionInterceptor

基类包含对应接口中每个方法的实现。使用基类,则可以不需要实现每个接口方法。如果,我们想要获取执行的SQL语句,那么继承DbCommandInterceptor这个基类即可。这里,我们先写个简单的取数接口,来看看EF Core生成的默认SQL语句是什么样的

1
2
3
4
public IEnumerable<User> Get()
{
return _demoContext.Users.ToList();
}


我们知道FirstFirstOrDefault是取一条数据,但是现在偏要让前面多条查询只返回一条数据呢。这里,我们就新建一个拦截器继承DbCommandInterceptor这个基类,并重写ReaderExecuting方法

1
2
3
4
5
6
7
8
public class ModifyDbCommandInterceptor: DbCommandInterceptor
{
public override InterceptionResult<DbDataReader> ReaderExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result)
{
command.CommandText= command.CommandText.Trim()+" limit 1";
return base.ReaderExecuting(command, eventData, result);
}
}

然后用AddInterceptors来注册我新加的拦截器

1
2
3
4
5
6
7
var serverVersion = new MySqlServerVersion(new Version(8, 0, 24));
string connectionString = builder.Configuration.GetConnectionString("MysqlConnectionString");
builder.Services.AddDbContext<DemoContext>(opt =>
{
opt.UseMySql(connectionString, serverVersion);
opt.AddInterceptors(new ModifyDbCommandInterceptor());
});


上图可以看到,我们修改的SQL产生了效果,当然,正常情况下肯定没人会这般无聊。那么什么时候,我们可能会用到拦截器呢?我大致想到这几种场景,如:改写SQL,有时候,EF Core生成的SQL可能不是我们想要的;缓存结果数据,有时候,我们可能想将查询的结果数据缓存起来。当然,通过其他方式来缓存查询结果也可以;审计操作日志,有时候,我们想要记录增删改的日志,等等。

EF Core拦截器获取或修改SQL语句

https://blogs.52fx.biz/posts/516819676.html

作者

eyiadmin

发布于

2022-05-23

更新于

2024-05-31

许可协议

评论