EF Core通过显式编译提高查询性能

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

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

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

  • EF.CompileQuery()
  • EF.CompileAsyncQuery()

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

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

实体定义以前数据库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通过显式编译提高查询性能的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • .net core实用技巧——将EF Core生成的SQL语句显示在控制台中

    前言 笔者最近在开发和维护一个.NET Core项目,其中使用几个非常有意思的.NET Core相关的扩展,在此总结整理一下. EF Core性能调优 如果你的项目中使用了EF Core, 且正在处于性能调优阶段,那么了解EF Core生成的SQL语句是非常关键的.那么除了使用第三方工具,如何查看EF Core生成的SQL语句呢?这里笔者将给出一个基于.NET Core内置日志组件的实现方式. 创建一个实例项目 我们首先建一个控制台程序,在主程序中我们编写了一个最简单的EF查询. class P

  • .net EF Core专题:EF Core 读取数据时发生了什么?

    原文:https://bit.ly/2UMiDLb 作者:Jon P Smith 翻译:王亮 声明:我翻译技术文章不是逐句翻译的,而是根据我自己的理解来表述的.其中可能会去除一些本人实在不知道如何组织但又不影响理解的句子. 本文将为你详细描绘 EF Core 从数据库中读取数据的"幕后"视图.我将揭开两种数据库读取方式的面纱:一个是普通的查询,另一个是使用 AsNoTracking 方法的非跟踪查询.我还将通过一个实验来演示我是如何解决我的一个客户遇到的性能问题. 我假设你对 EF C

  • ASP.NET Core使用EF SQLite对数据库增删改查

    SQLIte 操作方便,简单小巧,这里笔者就不再过多介绍,感兴趣可以到以下博文 https://www.jb51.net/article/234142.htm 文章介绍创建ASP.NET Core 程序,创建模型.上下文,生成数据库,对数据库增删查改. 并对每个过程进行详细介绍,使初学者尽快了解内容和相关知识,避免对某一知识点怀疑.卡在某个位置. 1 新建ASP.NET Core MVC 应用 1.1 新建MVC应用 打开Visual Studio 2017,新建 ASP.NET Web应用程序

  • ASP.Net Core基于EF6、Unitwork、Autofac实现Repository模式

    一.实现的思路和结构图 Repository的共同性 有一些公共的方法(增删改查), 这些方法无关于Repository操作的是哪个实体类,可以把这些方法定义成接口IRepository,然后有个基类BaseRepository实现该接口的方法.常见的方法,比如Find, Filter, Delete, Create等 Repository的差异性 每个Repository类又会有一些差异性,应当允许它们能够继承BaseRepository之外,还能够再扩展自己的一些方法.所以每个类都可以再定义

  • .net core EF Core调用存储过程的方式

    前言 在这里,我们将尝试去学习一下 .net core EF Core 中调用存储过程. 我们知道,EF Core 是不支持直接调用存储过程的,那它又提供了什么样的方式去执行存储过程呢?有如下方法: 1.FromSql,官方文档 DbSet<TEntity>.FromSql() 2.执行SQl命令 DbContext.Database.ExecuteSqlCommand() 但是,这两种方式都有局限性: 1.FromSql方式的结果一定要是实体类型,就是数据库表映射的模型.这意味着,执行存储过

  • .NET Core使用EF生成数据库出错的解决方法

    在.NET Core 项目钟(类库),使用Entity Framework,建立模型生成数据库时,失败 Could not load assembly 'xxx'. Ensure it is referenced by the startup project 'xxx'. 改成 64 位即可 假设 ef 代码 public class ApplicationDbContext : IdentityDbContext<User> { public ApplicationDbContext(DbC

  • EFCore 通过实体Model生成创建SQL Server数据库表脚本

    在我们的项目中经常采用Model First这种方式先来设计数据库Model,然后通过Migration来生成数据库表结构,有些时候我们需要动态通过实体Model来创建数据库的表结构,特别是在创建像临时表这一类型的时候,我们直接通过代码来进行创建就可以了不用通过创建实体然后迁移这种方式来进行,其实原理也很简单就是通过遍历当前Model然后获取每一个属性并以此来生成部分创建脚本,然后将这些创建的脚本拼接成一个完整的脚本到数据库中去执行就可以了,只不过这里有一些需要注意的地方,下面我们来通过代码来一

  • C# EF Core可视化工具的使用及EF Core入门语句操作代码

    目录 前言 一.EFCoreTools的下载 二.EFCoreTools的使用 1.新建项目并引入EFCoreTools 2.手动引入EFCore的包 三.EFCore的填查删改 1.添加操作 2.查找操作 3.删除操作 4.修改操作 四.总结 前言 Entity Framework (EF) Core 是轻量化.可扩展.开源和跨平台版的常用 Entity Framework 数据访问技术. 一.EF Core Tools的下载 EFCore Tools可视化工具下载后安装,并重启ViusalS

  • EF Core通过显式编译提高查询性能

    今天,我将向您展示这些EF Core中一个很酷的功能,通过使用显式编译的查询,提高查询性能. 不过在介绍具体内容之前,需要说明一点,EF Core已经对表达式的编译使用了缓存:当您的代码需要重用以前执行的查询时,EF Core将使用哈希查找并从缓存中返回已编译的查询. 不过,您可能希望直接对查询进行编译,跳过哈希的计算和缓存查找.我们可以通过在EF静态类中下面两个方法来实现: EF.CompileQuery() EF.CompileAsyncQuery() 这些方法允许您定义一个已编译的查询,然

  • 利用 SQL Server 过滤索引提高查询语句的性能分析

    大家好,我是只谈技术不剪发的 Tony 老师. Microsoft SQL Server 过滤索引(筛选索引)是指基于满足特定条件的数据行进行索引.与全表索引(默认创建)相比,设计良好的筛选索引可以提高查询性能.减少索引维护开销并可降低索引存储开销.本文就给大家介绍一下 Microsoft SQL Server 中的过滤索引功能. 在创建过滤索引之前,我们需要了解它的适用场景. 在某个字段中只有少量相关值需要查询时,可以针对值的子集创建过滤索引. 例如,当字段中的值大部分为 NULL 并且查询只

  • 如何在一个千万级的数据库查询中提高查询的效率?

    在实际项目中,当数据库的数据达到千万级别时候,普通查询效率直线下降,而且当使用的where条件较多,其查询效率是让人无法容忍的.假如一个taobao订单查询详情要几十秒,可想而知的用户体验是多差. 下面是一些优化方法: 一.数据库设计方面 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引: 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t w

  • 浅谈C++ Explicit Constructors(显式构造函数)

    C++ 为类(Class)提供了许多默认函数.如果自己没有申明,编译器会为我们提供一个copy构造函数.一个copy assignment操作符和一个析构函数.此外,如果没有申明任何构造函数,编译器会为我们申明一个default构造函数.很像下面的Empty类: class Empty{ public: Empty(); Empty(const Empty &rhs); ~Empty(); Empty& operator=(const Empty &rhs); }; 就像Effec

  • 在SQL Server数据库中为标识(IDENTITY)列插入显式值

    如果我们在标识列中插入值,例如: insert member(id,username) values(10,'admin') 则在查询分析器里面会返回错误信息:  引用内容 服务器: 消息 544,级别 16,状态 1,行 1 当 IDENTITY_Insert 设置为 OFF 时,不能向表 'member' 中的标识列插入显式值. 而在ASP程序中会返回错误信息:  引用内容 Microsoft OLE DB Provider for SQL Server 错误 '80040e14' 当 ID

  • C#显式地实现接口成员的方法

    本文实例讲述了C#显式地实现接口成员的方法.分享给大家供大家参考.具体实现方法如下: // explicit1.cs interface IDimensions { float Length(); float Width(); } class Box : IDimensions { float lengthInches; float widthInches; public Box(float length, float width) { lengthInches = length; widthI

  • c++显式类型转换示例详解

    标准C++包含一个显式的转换语法: static_cast:用于"良性"和"适度良性"的转换,包括不用强制转换 const_cast:用于"const"和/或"volatile"进行转换 reinterpret_cast:转换为完全不同的意思.为了安全的使用它,关键必须转换回原来的类型.转换成的类型一般只能用于位操作,否则就是为了其他隐秘的目的.这是所有转换中最危险的. dynamic_cast:用于类型安全的向下转换 ---

  • 深入理解java内置锁(synchronized)和显式锁(ReentrantLock)

    synchronized 和 Reentrantlock 多线程编程中,当代码需要同步时我们会用到锁.Java为我们提供了内置锁(synchronized)和显式锁(ReentrantLock)两种同步方式.显式锁是JDK1.5引入的,这两种锁有什么异同呢?是仅仅增加了一种选择还是另有其因?本文为您一探究竟. // synchronized关键字用法示例 public synchronized void add(int t){// 同步方法 this.v += t; } public stati

  • JavaScript显式数据类型转换详解

    基本概念 将值从一种类型转换为另一种类型称为类型转换,类型转换总是返回基本类型值,如字符串.数字和布尔值,不会返回引用类型值. 类型转换分为"显式"和"隐式":"显式"转换发生在静态类型语言的编译阶段,而"隐式"转换则发生在动态类型语言的运行时. 显式类型转换 非字符串到字符串的类型转换 toString() 方法 数字.布尔值.字符串和对象都有 toString() 方法,但 null 和 undefined 没有. 例子:

随机推荐