今天,我将向您展示这些EF Core中一个很酷的功能,通过使用显式编译的查询,提高查询性能。

不过在介绍具体内容之前,需要说明一点,EF Core已经对表达式的编译使用了缓存;当您的代码需要重用以前执行的查询时,EF Core将使用哈希查找并从缓存中返回已编译的查询。

关于这一点,您可以查阅github上面的代码QueryCompiler.cs

不过,您可能希望直接对查询进行编译,跳过哈希的计算和缓存查找。我们可以通过在EF静态类中下面两个方法来实现:

这些方法允许您定义一个已编译的查询,然后通过调用一个委托调用它。

如果您对表达式的哈希计算感兴趣,可以看一看它的实现,非常复杂,ExpressionEqualityComparer.cs

为了避免因为数据库查询产生测试结果的差异,我们这里使用内存数据库,它开销更小,同时也可以避免数据库优化执行计划以及缓存所带来的问题。

实体定义以前数据库DbContext

定义实体

在这我们定义一个Category实体类型,非常简单,只有两个属性。

    public class Category
{
public Guid Id { get; set; }
public string Name { get; set; }
}

数据库DbContext

FillCategories方法中,将内存数据库中增加三条记录。

    public class TestDbContext : DbContext
{
public TestDbContext(DbContextOptions<TestDbContext> options) : base(options)
{
} public DbSet<Category> Categories { get; set; } public void FillCategories()
{
var foodCategory = new Category {
Id = Guid.NewGuid(),
Name = "Food"
}; Categories.AddRange(foodCategory, new Category {
Id = Guid.NewGuid(),
Name = "Drinks"
}, new Category {
Id = Guid.NewGuid(),
Name = "Clothing"
}, new Category {
Id = Guid.NewGuid(),
Name = "Electronis"
}); SaveChanges(true);
}
}

测试代码

    public class CompileQueryTest
{
private Func<TestDbContext, Guid, Category> _getCategory =
EF.CompileQuery((TestDbContext context, Guid id) => context.Categories.FirstOrDefault(c => c.Id == id)); private readonly TestDbContext _dbContext; public CompileQueryTest()
{
var options = new DbContextOptionsBuilder<TestDbContext>().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;
var context = new TestDbContext(options); context.FillCategories(); _dbContext = context;
} private readonly Guid _queryId = Guid.NewGuid(); [Benchmark]
public void CompiledQuery()
{
_ = _getCategory(_dbContext, _queryId);
} [Benchmark]
public void UnCompiledQuery()
{ _ = _dbContext.Categories.FirstOrDefault(c => c.Id == _queryId); }
}

为了更加接近测试结果,我们在构造函数中创建TestDbContext对象以及填充数据库。

测试结果

我们使用Benchmark.Net进行基准测试,测试结果如下:

Method Mean Error StdDev
CompiledQuery 10.59 us 0.0580 us 0.0543 us
UnCompiledQuery 79.55 us 0.7860 us 0.7353 us

经过编译的查询比未编译过的查询存在接近8倍的差距。如果您对这个功能感兴趣,不防自己测试一下。

EF Core 使用编译查询提高性能的更多相关文章

  1. 深入理解 EF Core:使用查询过滤器实现数据软删除

    原文:https://bit.ly/2Cy3J5f 作者:Jon P Smith 翻译:王亮 声明:我翻译技术文章不是逐句翻译的,而是根据我自己的理解来表述的.其中可能会去除一些本人实在不知道如何组织 ...

  2. EF Core 的关联查询

    0 前言 本文会列举出 EF Core 关联查询的方法: 在第一.二.三节中,介绍的是 EF Core 的基本能力,在实体中配置好关系,即可使用,且其使用方式,与编程思维吻合,是本文推荐的方式. 第四 ...

  3. EF core的原生SQL查询以及用EF core进行分页查询遇到的问题

    在用.net core进行数据库访问,需要处理一些比较复杂的查询,就不得不用原生的SQL查询了,然而EF Core 和EF6 的原生sql查询存在很大的差异. 在EF6中我们用SqlQuery和Exe ...

  4. Dapper, Ef core, Freesql 插入大量数据性能比较(一)

    需求:导入9999行数据时Dapper, Ef core, Freesql 谁的性能更优,是如何执行的,级联增加谁性能更佳. 确认方法:sql server 的 sys.dm_exec_query_s ...

  5. Dapper, Ef core, Freesql 插入大量数据性能比较(二)

    在上一篇文章中,我们比较出单表插入9999行数据,Dapper > EfCore > Freesql.在本文中,我们来看看级联插入 构建9999行数据 List<Entity> ...

  6. EntityFramework Core 2.0 Explicitly Compiled Query(显式编译查询)

    前言 EntityFramework Core 2.0引入了显式编译查询,在查询数据时预先编译好LINQ查询便于在请求数据时能够立即响应.显式编译查询提供了高可用场景,通过使用显式编译的查询可以提高查 ...

  7. 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 ...

  8. EF 6.x、EF Core实现dynamic动态查询和EF Core实现多个上下文实例池你了解多少?

    前言 很长一段时间没有写博客了,今天补上一篇吧,偶尔发现不太愿意写博客了,太耗费时间,不过还是在坚持当中,毕竟或许写出来的东西能帮到一些童鞋吧,接下来我们直奔主题.无论是在在EF 6.x还是EF Co ...

  9. 讨论过后而引发对EF 6.x和EF Core查询缓存的思考

    前言 最近将RabbitMQ正式封装引入到.NET Core 2.0项目当中,之前从未接触过是个高大上的东东跟着老大学习中,其中收获不少,本打算再看看RabbitMQ有时间写写,回来后和何镇汐大哥探讨 ...

随机推荐

  1. Android执行时ART载入类和方法的过程分析

    在前一篇文章中.我们通过分析OAT文件的载入过程,认识了OAT文件的格式,当中包括了原始的DEX文件. 既然ART运行时运行的都是翻译DEX字节码后得到的本地机器指令了.为什么还须要在OAT文件里包括 ...

  2. ajaxSetup设置Ajax请求的默认值

    ajaxSetup() 方法为将来的 AJAX 请求设置默认值.语法$.ajaxSetup({name:value, name:value, ... }) 该参数为带有一个或多个名称/值对的 AJAX ...

  3. idea 安装热部署插件

    jrebel(http://zeroturnaround.com/)的作用就是当你的代码改变时,你不需要重启服务,节省了时间.代码的改变有很多种,比如增加class.在class中增加方法等等.下面介 ...

  4. List集合在遍历过程中的删除

    List集合在遍历过程中的删除:[1,1,2,3,4,5] for循环正续会漏掉一个1 for(int i=0;i<list.size();i++){ if(list.get(i).equals ...

  5. CenOS 6.5下 mysql自动备份

      1.mysql备份命令是mysqldump,自动执行可以用cron,但是文件名需要带有时间标志,shell处理起来很麻烦,我就选择了python来解决 2.文件名用time模块来解决,执行系统命令 ...

  6. 2.python数据类型

    1 Number(数字) 2   字符串类型(string)   字符串内置方法 # string.capitalize() 把字符串的第一个字符大写 # string.center(width) 返 ...

  7. JavaScript循环实例

    几个经典的循环案例: 1.一张纸的厚度是0.0001米,将纸对折,对折多少次厚度超过珠峰高度8848米 var i=0; var h=0.0001; while(true){ i++; h=h*2; ...

  8. linux使用freetds 连接连远程服务器sqlservser2012

    1.下载:freetds-patched.tar.gz  http://www.freetds.org/software.html http://www.freetds.org/userguide/c ...

  9. C++ 头文件系列(iostream)

    1. 简介 这个头文件非常特殊,它只声明了8个常用流对象. 2. 8个对象 2.1 窄字符对象(char) extern istream cin extern ostream cout extern ...

  10. Spring基础篇——DI和AOP初识

    前言 作为从事java开发的码农,Spring的重要性不言而喻,你可能每天都在和Spring框架打交道.Spring恰如其名的,给java应用程序的开发带了春天般的舒爽感觉.Spring,可以说是任何 ...