EntityFramework Core 3.x添加查询提示(NOLOCK)
前言
今天看到有园友写了一篇关于添加NOLOCK查询提示的博文《https://www.cnblogs.com/weihanli/p/12623934.html》,这里呢,我将介绍另外一种添加查询提示的方法,此方式源于我看过源码后的实现,孰好孰歹,请自行判之,接下来我们一起来看看。
查询提示(NOLOCK)
在EntityFramework中,如需要添加查询提示需要自定义实现拦截器,但在EntityFramework Core中除了支持实现自定义拦截器外,还可以通过继承自对应类进行复写,那就是QuerySqlGenerator类,存在于命名空间【Microsoft.EntityFrameworkCore.Query】,在此类通过我们所写的表达式实现所有查询组合,比如我们需要用到的对表的设置,如下:
protected override Expression VisitTable(TableExpression tableExpression)
{
_relationalCommandBuilder
.Append(_sqlGenerationHelper.DelimitIdentifier(tableExpression.Name, tableExpression.Schema))
.Append(AliasSeparator)
.Append(_sqlGenerationHelper.DelimitIdentifier(tableExpression.Alias)); return tableExpression;
}
同时我们可以看到还有另外一个类SqlServerQuerySqlGenerator继承自上述类,若我们需要重写的话继承自此类即可,比如在此类中进一步重写了三个表达式,我们随便看一个,如下:
protected override void GenerateTop(SelectExpression selectExpression)
{
if (selectExpression.Limit != null
&& selectExpression.Offset == null)
{
Sql.Append("TOP("); Visit(selectExpression.Limit); Sql.Append(") ");
}
}
上述意在表明:当我们进行在内存中通过Skip和Take进行分页时,因为Skip会翻译成Offset,而Take会翻译成Limit,若我们直接跳过Skip而写Take,此时在生成的Sql语句中添加TOP,很显然这是合情合理而且合法的。举个栗子,如下:
var context = new EFCoreDbContext();
context.Database.EnsureCreated(); var blogs = context.Blogs.Take().ToList();
那么此类是何时进行实例化的呢?通过SqlServerQuerySqlGeneratorFactory工厂类实例化,如下:
public class SqlServerQuerySqlGeneratorFactory : IQuerySqlGeneratorFactory
{
private readonly QuerySqlGeneratorDependencies _dependencies; public SqlServerQuerySqlGeneratorFactory(QuerySqlGeneratorDependencies dependencies)
{
_dependencies = dependencies;
} public virtual QuerySqlGenerator Create()
=> new SqlServerQuerySqlGenerator(_dependencies);
}
那么上述Sql查询工厂类到底具体是在什么时候被注册的呢,如下已省略其他注册类:
public static IServiceCollection AddEntityFrameworkSqlServer([NotNull] this IServiceCollection serviceCollection)
{
Check.NotNull(serviceCollection, nameof(serviceCollection)); var builder = new EntityFrameworkRelationalServicesBuilder(serviceCollection) // New Query Pipeline
.TryAdd<IQuerySqlGeneratorFactory, SqlServerQuerySqlGeneratorFactory>() builder.TryAddCoreServices(); return serviceCollection;
}
通过上述AddEntityFrameworkSqlServer名称可猜测该方法肯定是在实例化上下文时注册所有需要用到的接口具体实现,有了这个就好办了,为了不破坏原有的实现,我们自定义Sql查询生成类并继承自SqlServerQuerySqlGenerator并重写对表的设置并添加NOLOCK查询提示,如下:
public class CustomSqlServerQuerySqlGenerator : SqlServerQuerySqlGenerator
{
public CustomSqlServerQuerySqlGenerator(QuerySqlGeneratorDependencies dependencies)
: base(dependencies) { }
protected override Expression VisitTable(TableExpression tableExpression)
{
var result = base.VisitTable(tableExpression);
Sql.Append(" WITH (NOLOCK)");
return result;
}
}
接下来我们则需要实现自定义查询工厂并继承自默认提供的查询工厂类从而实例化上述自定义的查询类,如下:
public class CustomSqlServerQuerySqlGeneratorFactory : SqlServerQuerySqlGeneratorFactory
{
private readonly QuerySqlGeneratorDependencies _dependencies;
public CustomSqlServerQuerySqlGeneratorFactory(QuerySqlGeneratorDependencies dependencies)
: base(dependencies)
{
_dependencies = dependencies;
}
public override QuerySqlGenerator Create() =>
new CustomSqlServerQuerySqlGenerator(_dependencies);
}
那我们如何将默认提供的查询工厂类替换为上述自定义查询工厂类呢?稍微对DbContextOptionsBuilder类有所了解的童鞋应该知道,在该类中提供了ReplaceService方法来给我们替换EF Core中默认的实现,如下:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseLoggerFactory(loggerFactory)
.UseSqlServer(@"Server=.;Database=EFCore;Trusted_Connection=True;")
.ReplaceService<IQuerySqlGeneratorFactory, CustomSqlServerQuerySqlGeneratorFactory>();
到此就已经实现了添加NOLOCK查询提示,对于此种实现方式同样应该也适用于2.x版本,只不过稍微注意下对于自定义类构造函数参数可能略有不同,对于自定义实现,还是写成扩展方法比较好,这样也方便统一管理,看个人诺,比如写成如下:
public static class CustomDbContextOptionsBuilderExtensions
{
public static DbContextOptionsBuilder UseCustomSqlServerQuerySqlGenerator(this DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.ReplaceService<IQuerySqlGeneratorFactory, CustomSqlServerQuerySqlGeneratorFactory>();
return optionsBuilder;
}
}
总结
通过拦截器或者本节从源头生成Sql语句时添加对表的查询提示皆可,到底哪一个好呢?自行判断吧,其他就没啥可以进行总结的了,暂时到此为止吧。
EntityFramework Core 3.x添加查询提示(NOLOCK)的更多相关文章
- EntityFramework Core 学习笔记 —— 添加主键约束
原文地址:https://docs.efproject.net/en/latest/modeling/keys.html Keys (primary) Key 是每个实体例的主要唯一标识.EF Cor ...
- EntityFramework Core 2.0执行原始查询如何防止SQL注入?
前言 接下来一段时间我们来讲讲EntityFramework Core基础,精简的内容,深入浅出,希望为想学习EntityFramework Core的童鞋提供一点帮助. EntityFramewor ...
- EntityFramework Core笔记:查询数据(3)
1. 基本查询 1.1 加载全部数据 using System.Linq; using (var context = new LibingContext()) { var roles = contex ...
- EntityFramework Core Raw SQL
前言 本节我们来讲讲EF Core中的原始查询,目前在项目中对于简单的查询直接通过EF就可以解决,但是涉及到多表查询时为了一步到位就采用了原始查询的方式进行.下面我们一起来看看. EntityFram ...
- EntityFramework Core查询问题集锦(一)
前言 和大家脱离了一段时间,有时候总想着时间挤挤总是会有的,但是并非人愿,后面会借助周末的时间来打理博客,如有问题可以在周末私信我或者加我QQ皆可,欢迎和大家一起探讨,本节我们来讨论EF Core中的 ...
- Cookies 初识 Dotnetspider EF 6.x、EF Core实现dynamic动态查询和EF Core注入多个上下文实例池你知道有什么问题? EntityFramework Core 运行dotnet ef命令迁移背后本质是什么?(EF Core迁移原理)
Cookies 1.创建HttpCookies Cookie=new HttpCookies("CookieName");2.添加内容Cookie.Values.Add(&qu ...
- 创建ASP.NET Core MVC应用程序(5)-添加查询功能 & 新字段
创建ASP.NET Core MVC应用程序(5)-添加查询功能 & 新字段 添加查询功能 本文将实现通过Name查询用户信息. 首先更新GetAll方法以启用查询: public async ...
- 为什么NOLOCK查询提示是个不明智的想法
一些人总当NOLOCK查询提示是SQL Server里的加速器,因为它避免了大量的死锁情景.在这篇文章里,我想向你展示下为什么NOLOCK查询提示是个不好的想法. 脏读(Dirty Reads) NO ...
- EntityFramework Core 2.0 Explicitly Compiled Query(显式编译查询)
前言 EntityFramework Core 2.0引入了显式编译查询,在查询数据时预先编译好LINQ查询便于在请求数据时能够立即响应.显式编译查询提供了高可用场景,通过使用显式编译的查询可以提高查 ...
随机推荐
- LeetCode 题解 | 1. 两数之和
题目描述: 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用. 示例: 给定 nums = [2, 7, 11, 15], t ...
- ZYNQ自定义AXI总线IP应用——PWM实现呼吸灯效果
一.前言 在实时性要求较高的场合中,CPU软件执行的方式显然不能满足需求,这时需要硬件逻辑实现部分功能.要想使自定义IP核被CPU访问,就必须带有总线接口.ZYNQ采用AXI BUS实现PS和PL之间 ...
- Java设计模式之结构模式
一.外观模式 分析:外观模式是为子系统的一组接口提供一个统一的界面,数据库JDBC连接应用就是外观模式的一个典型例子,特点:降低系统的复杂度,增加灵活性.结果:代码示例: public class D ...
- 前端如何真正晋级成全栈:腾讯 Serverless 前端落地与实践
Serverless 是当下炙手可热的技术,被认为是云计算发展的未来方向,拥有免运维.降低开发成本.按需自动扩展等诸多优点.尤其是在前端研发领域,使用 Node 开发云函数,可以让前端工程师更加专注于 ...
- celery异步任务框架
目录 Celery 一.官方 二.Celery异步任务框架 Celery架构图 消息中间件 任务执行单元 任务结果存储 三.使用场景 四.Celery的安装配置 五.两种celery任务结构:提倡用包 ...
- JavaScript sort() 对json进行排序(数组)
function up(x,y){//升序 return x[val.prop] - y[val.prop] } function down(x,y){//降序 return y[val.prop] ...
- Java锁的理解
目录: 1.为什么要使用锁? 2.锁的类型? 1.为什么要使用锁? 通俗的说就是多个线程,也可以说多个方法同时对一个资源进行访问时,如果不加锁会造成线程安全问题.举例:比如有两张票,但是有5个人进来买 ...
- Go组件学习:如何读取ini配置文件
代码示例全部保存在,欢迎star:https://github.com/EnochZg/golang-examples 安装组件 go get gopkg.in/ini.v1 使用 先创建ini后缀的 ...
- Keil MDK版兼容51系列单片机开发环境安装
一.安装源文件下载 百度网盘链接:https://pan.baidu.com/s/18tnjFgVat4q2hDSh7LAD8A 提取码: 2295 二.安装及破解 1.安装51的编辑器 双击安 ...
- web自动化的三大等待
由于web网页打开后需要时间进行数据的传送,页面的渲染,所以我们在写web自动化脚本的时候,需要等待它加载完所有的页面元素,我们才进行操作或点击.同时这种等待也是为了提高脚本的稳定性. seleniu ...