给 EF Core 查询增加 With NoLock
程序员文章站
2022-03-12 18:48:34
EF Core 在 3.x 版本中增加了 `Interceptor`,使得我们可以在发生低级别数据库操作时作为 EF Core 正常运行的一部分自动调用它们。 例如,打开连接、提交事务或执行命令时。所以我们可以自定义一个 `Interceptor` 来记录执行的 sql 语句,也可以通过 `In... ......
给 ef core 查询增加 with nolock
intro
ef core 在 3.x 版本中增加了 interceptor
,使得我们可以在发生低级别数据库操作时作为 ef core 正常运行的一部分自动调用它们。 例如,打开连接、提交事务或执行命令时。
所以我们可以自定义一个 interceptor
来记录执行的 sql 语句,也可以通过 interceptor
来实现 sql 语句的执行前的修改或者更准确的记录 dbcommand 执行的耗时。
这里我们可以借助 interceptor
实现对于查询语句的修改,自动给查询语句加 (with nolock)
,with nolock
等效于 read uncommited
(读未提交)的事务级别,这样可能会造成一定的脏读,但是从效率上而言,是比较高效的,不会因为别的事务长时间未提交导致查询阻塞,所以对于大数据多事务的场景下,查询 sql 加 nolock
还是比较有意义的
nolockinterceptor
继承 dbcommandinterceptor
,重写查询 sql 执行之前的操作,在执行查询 sql 之前增加 with(nolock)
,实现代码如下:
public class querywithnolockdbcommandinterceptor : dbcommandinterceptor { private static readonly regex tablealiasregex = new regex(@"(?<tablealias>as \[[a-za-z]\w*\](?! with \(nolock\)))", regexoptions.multiline | regexoptions.compiled | regexoptions.ignorecase); public override interceptionresult<object> scalarexecuting(dbcommand command, commandeventdata eventdata, interceptionresult<object> result) { command.commandtext = tablealiasregex.replace( command.commandtext, "${tablealias} with (nolock)" ); return base.scalarexecuting(command, eventdata, result); } public override task<interceptionresult<object>> scalarexecutingasync(dbcommand command, commandeventdata eventdata, interceptionresult<object> result, cancellationtoken cancellationtoken = new cancellationtoken()) { command.commandtext = tablealiasregex.replace( command.commandtext, "${tablealias} with (nolock)" ); return base.scalarexecutingasync(command, eventdata, result, cancellationtoken); } public override interceptionresult<dbdatareader> readerexecuting(dbcommand command, commandeventdata eventdata, interceptionresult<dbdatareader> result) { command.commandtext = tablealiasregex.replace( command.commandtext, "${tablealias} with (nolock)" ); return result; } public override task<interceptionresult<dbdatareader>> readerexecutingasync(dbcommand command, commandeventdata eventdata, interceptionresult<dbdatareader> result, cancellationtoken cancellationtoken = new cancellationtoken()) { command.commandtext = tablealiasregex.replace( command.commandtext, "${tablealias} with (nolock)" ); return base.readerexecutingasync(command, eventdata, result, cancellationtoken); } }
interceptor 的使用
在注册 dbcontext
服务的时候,可以配置 interceptor
,配置如下:
var services = new servicecollection(); services.adddbcontext<testdbcontext>(options => { options .useloggerfactory(loggerfactory) .usesqlserver(dbconnectionstring) .addinterceptors(new querywithnolockdbcommandinterceptor()) ; });
使用效果
通过 loggerfactory 记录的日志查看查询执行的 sql 语句
可以看到查询语句自动加上了 with (nolock)
reference
上一篇: ps怎么给图片中的人物添加外发光效果?
下一篇: 图的连通分量(利用邻接表存储信息)
推荐阅读
-
(24)ASP.NET Core EF查询(查询的工作原理、跟踪与非跟踪查询)
-
EF core的原生SQL查询以及用EF core进行分页查询遇到的问题
-
asp.net core系列 29 EF模型配置(查询类型,关系数据库建模)
-
asp.net core系列 32 EF查询数据 必备知识(1)
-
EF Core使用SQL调用返回其他类型的查询
-
使用IDbCommandInterceptor解决EF-CORE-3.x-使用MYSQL时,未正常的生成LIKE查询语句
-
在.Net Core WebAPI下给Swagger增加导出离线文档功能
-
asp.net core系列 33 EF查询数据 (2)
-
(25)ASP.NET Core EF查询(复杂查询运算符、原生SQL查询、异步查询)
-
学习ASP.NET Core Razor 编程系列九——增加查询功能