前几天看到有博客园中有园友写了一篇关于添加NOLOCK查询提示的博文,这里呢,我将介绍另外一种添加查询提示的方法,此方式源于我看过源码后的实现,孰好孰歹,请自行判之,接下来我们一起来看看。
在EntityFramework中,如需要添加查询提示需要自定义实现拦截器,但在EntityFramework Core中除了支持实现自定义拦截器外,还可以通过继承自对应类进行复写,那就是QuerySqlGenerator类,存在于命名空间【Microsoft.EntityFrameworkCore.Query】,在此类通过我们所写的表达式实现所有查询组合,比如我们需要用到的对表的设置,如下:
从源码中可看到SqlServerQuerySqlGenerator类继承自上述类,若我们需要重写的话继承自此类即可,比如在此类中进一步重写了三个表达式,我们随便看一个,如下:
上述意在表明:当我们进行在内存中通过Skip和Take进行分页时,因为Skip会翻译成Offset,而Take会翻译成Limit,若我们直接跳过Skip而写Take,此时在生成的Sql语句中添加TOP,很显然这是合情合理而且合法的。举个栗子,如下:
那么此类是何时进行实例化的呢?通过SqlServerQuerySqlGeneratorFactory工厂类实例化,如下:
那么上述Sql查询工厂类到底具体是在什么时候被注册的呢,如下已省略其他注册类:
通过上述AddEntityFrameworkSqlServer名称可猜测该方法肯定是在实例化上下文时注册所有需要用到的接口具体实现,有了这个就好办了,为了不破坏原有的实现,我们自定义Sql查询生成类并继承自SqlServerQuerySqlGenerator并重写对表的设置并添加NOLOCK查询提示,如下:
接下来我们则需要实现自定义查询工厂并继承自默认提供的查询工厂类从而实例化上述自定义的查询类,如下:
那我们如何将默认提供的查询工厂类替换为上述自定义查询工厂类呢?稍微对DbContextOptionsBuilder类有所了解的童鞋应该知道,在该类中提供了ReplaceService方法来给我们替换EF Core中默认的实现,如下:
到此就已经实现了添加NOLOCK查询提示,对于此种实现方式同样应该也适用于2.x版本,只不过稍微注意下对于自定义类构造函数参数可能略有不同,对于自定义实现,还是写成扩展方法比较好,这样也方便统一管理,看个人诺,比如写成如下:
通过拦截器或者本节从源头生成Sql语句时添加对表的查询提示皆可,到底哪一个好呢?自行判断吧,其他就没啥可以进行总结的了,暂时到此为止吧。