前言

EntityFramework Core 2.0引入了显式编译查询,在查询数据时预先编译好LINQ查询便于在请求数据时能够立即响应。显式编译查询提供了高可用场景,通过使用显式编译的查询可以提高查询性能。EF Core已经使用查询表达式的散列来表示自动编译和缓存查询,当我们的代码需要重用以前执行的查询时,EF Core将使用哈希查找并从缓存中返回已编译的查询。我们更希望直接使用编译查询绕过散列计算和高速缓存查找。

EntityFramework Core 2.0显式编译查询

比如我们要从博客实体中通过主键查询博客同时饥饿加载发表文章的集合列表,如下:

            var id = ;
using (var context = new EFCoreDbContext())
{
var blog = context.Blogs
.AsNoTracking()
.Include(c => c.Posts)
.Where(c => c.Id == id)
.FirstOrDefault();
}

当进行上述查询时,此时要经过编译翻译阶段最终返回实际结果,比如在Web网站上这样的请求很频繁,此时将严重影响响应速度导致页面加载数据过慢。从Web程序应用角度来看我们大可利用ASP.NET Core中的响应式缓存,在实际应用中我们会将查询封装为方法来使用,我们无法优化结果和查询方式,但是我们能够通过编译查询来提前保存好数据以达到缓存的效果。通过EF静态类中的扩展方法CompileQuery来实现。如下:

        static async Task<Blog> GetBlogAsync(EFCoreDbContext context, int id)
{
Func<EFCoreDbContext, int, Task<Blog>> blog = EF.CompileAsyncQuery((EFCoreDbContext context, int Id) =>
context.Blogs.Include(c => c.Posts)
.Where(c => c.Id == Id)
.FirstOrDefault());
return await blog(context, id);
}

常规查询和显式编译查询性能比较

接下来我们测试常规查询和使用显式编译查询的性能,我们利用EF Core提供的内存数据库来测试避免使用SQL Server数据库,利用SQL Server数据库很难去比较二者性能问题,因为数据库会进行查询计划优化和缓存,利用内存数据库只知道当前执行的查询不会进行任何优化, 首先我们下载EF Core内存数据库。额外再说明一点内存数据库在进行单元测试时很有意义。

接下来我们首先测试常规查询,我们预先在内存数据库中创建50条记录,然后查询十万次数据,这样来看每一次查询都会再次重新编译。

        public static void Main(string[] args)
{
var options = new DbContextOptionsBuilder<EFCoreDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
var context = new EFCoreDbContext(options); var stopWatch = new Stopwatch();
FillBlogs(context);
stopWatch.Start();
for (var i = ; i < ; i++)
{
GetUnCompileQueryBlog(context);
}
stopWatch.Stop();
Console.Write("Compiling time:");
Console.WriteLine(stopWatch.Elapsed);
Console.ReadKey();
} static void FillBlogs(EFCoreDbContext context)
{
for (var i = ; i < ; i++)
{
context.Blogs.Add(new Blog
{
Name = "Jeffcky",
CreatedTime = DateTime.Now,
Url = "http://www.cnblogs/com/CreateMyself",
ModifiedTime = DateTime.Now,
Posts = new List<Post>()
{
new Post()
{
CommentCount = i, CreatedTime = DateTime.Now,
ModifiedTime = DateTime.Now, Name = "EF Core"
}
}
});
}
context.SaveChanges(true);
} static Blog GetUnCompileQueryBlog(EFCoreDbContext context)
{
return context.Blogs.Include(c => c.Posts)
.OrderBy(o => o.Id)
.FirstOrDefault();
}

我们看到上述利用常规查询总耗时27秒,接下来我们再来看看显式编译查询耗时情况。

private static Func<EFCoreDbContext, Blog> _getCompiledBlog = EF.CompileQuery((EFCoreDbContext context) =>
context.Blogs.Include(c => c.Posts)
.OrderBy(o => o.Id)
.FirstOrDefault());
            var options = new DbContextOptionsBuilder<EFCoreDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
var context = new EFCoreDbContext(options); var stopWatch = new Stopwatch();
FillBlogs(context);
stopWatch.Start();
for (var i = ; i < ; i++)
{
GetCompileQueryBlog(context);
}
stopWatch.Stop();
Console.Write("Compiling time:");
Console.WriteLine(stopWatch.Elapsed);
Console.ReadKey();

如上通过显式编译查询耗时16秒,那么是不是就说明显式编译查询性能一定优于常规查询呢?显然不是这样,上述只是简单的测试方法,有可能运行多次显式编译查询性能还低于常规查询,所以上述简单的测试方法并不能看出常规查询和显式编译查询之间的性能差异,当查询基数足够大时则能通过机器明显看出二者之间的性能差异,这也就说明了为什么EntityFramework Core官方文档说明显式编译查询的高可用。但是显式编译查询还有且缺点,当我们进行如下查询呢?

        public static void Main(string[] args)
{
var options = new DbContextOptionsBuilder<EFCoreDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
var context = new EFCoreDbContext(options); var blogs = GetCompileQueryBlogs(context); Console.ReadKey();
} static Blog[] GetCompileQueryBlogs(EFCoreDbContext context)
{
Func<EFCoreDbContext, Blog[]> func = EF.CompileQuery((EFCoreDbContext db) =>
db.Blogs.Include(c => c.Posts)
.OrderBy(o => o.Id)
.ToArray()); return func(context);
}
}

当前EntityFramework Core 2.0.1版本对于显式编译查询还不支持返回IEnumerable<T>, IQueryable<T>的集合类型,期待未来能够有所支持。

总结缺陷

显式编译查询提供高可用场景,但是仍然存在其缺陷,期待未来能有更多支持,希望给阅读的您一点帮助。精简的内容,简单的讲解,希望对阅读的您有所帮助,我们明天再会。

EntityFramework Core 2.0 Explicitly Compiled Query(显式编译查询)的更多相关文章

  1. EntityFramework Core 2.0执行原始查询如何防止SQL注入?

    前言 接下来一段时间我们来讲讲EntityFramework Core基础,精简的内容,深入浅出,希望为想学习EntityFramework Core的童鞋提供一点帮助. EntityFramewor ...

  2. EntityFramework Core 2.0全局过滤(HasQueryFilter)

    前言 EntityFramework Core每一次版本的迭代和更新都会带给我们惊喜,每次都会尽量满足大部分使用者的需求.在EF Core 2.0版本中出现了全局过滤新特性即HasQueryFilte ...

  3. .NetCore技术研究-EntityFramework Core 3.0 Preview

    前段时间.Net Core 3.0 发布了,Entity Framework Core 3.0 也发布了Preview版.假期用了一上午大致研究了一遍,同时又体验了一把Visual Studio 20 ...

  4. EntityFramework Core 2.0自定义标量函数两种方式

    前言 上一节我们讲完原始查询如何防止SQL注入问题同时并提供了几种方式.本节我们继续来讲讲EF Core 2.0中的新特性自定义标量函数. 自定义标量函数两种方式 在EF Core 2.0中我们可以将 ...

  5. EntityFramework Core 3.0查询

    前言 随着.NET Core 3.0的发布,EF Core 3.0也随之正式发布,关于这一块最近一段时间也没太多去关注,陆续会去对比之前版本有什么变化没有,本节我们来看下两个查询. 分组 我们知道在E ...

  6. CSS3 Media Query 响应式媒体查询

    在CSS中,有一个极其实用的功能:@media 响应式布局.具体来说,就是可以根据客户端的介质和屏幕大小,提供不同的样式表或者只展示样式表中的一部分.通过响应式布局,可以达到只使用单一文件提供多平台的 ...

  7. Entity Framework Core 2.0 新特性

    本文翻译来自:https://docs.microsoft.com/en-us/ef/core/what-is-new/index 一.模型级查询过滤器(Model-level query filte ...

  8. 《你必须掌握的Entity Framework 6.x与Core 2.0》书籍出版

    前言 到目前为止写过刚好两百来篇博客,看过我博客的读者应该大概知道我每一篇博客都沿袭着一贯的套路,从前言到话题最终到总结,本文依然是一如既往的套路,但是不是介绍技术,也可说是介绍技术,不过是介绍书中的 ...

  9. .Net Core 2.0生态(4):Entity Framework Core 2.0 特性介绍和使用指南

    前言 这是.Net Core 2.0生态生态介绍的最后一篇,EF一直是我喜欢的一个ORM框架,随着版本升级EF也发展到EF6.x,Entity Framework Core是一个支持跨平台的全新版本, ...

随机推荐

  1. BZOJ 4767: 两双手 [DP 组合数]

    传送门 题意: 给你平面上两个向量,走到指定点,一些点不能经过,求方案数 煞笔提一开始被题面带偏了一直郁闷为什么方案不是无限 现在精简的题意.....不就是$bzoj3782$原题嘛,还不需要$Luc ...

  2. ASP.NET Core 2.0 : 四. _Layout与_ViewStart

    本章我们新建一个项目,并通过这个项目熟悉一下_Layout与_ViewStart. 新建一个项目 首先, 文件->新建一个解决方案 选择.Net Core 的APP下面的ASP.NET Core ...

  3. Docker Compose容器编排

    Compose是Docker官方的开源项目,可以实现对Docker容器集群的快速编排.Compose 中有两个重要的概念:服务(service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实 ...

  4. ORM规约变更经典案例---mysql军规

    先介绍一下<MySQL数据库开发的三十六条军规>,这里只介绍核心的,具体内容大家可以自行百度,这是从底层开发人员到管理者必须知道规范.出自58赶集. 写在前面的话: 总是在灾难发生后,才想 ...

  5. 走进JavaScript——重拾函数

    创建函数 通过构造器的方式来创建函数,最后一个参数为函数体其他为形参 new Function('a','b','alert(a)') /* function anonymous(a,b) { ale ...

  6. tcp_sync_server and tcp_sync_client

    #include <iostream> #include <fstream> #include <sstream> #include <boost/asio. ...

  7. 常用VI操作命令

    # ------------------- VI basic ------------------------------- # file name: VI_basic # author : # da ...

  8. c中const定义的问题

    /* 这题有个疑问: const double BASE1=BREAK1*RATE1; //第二个分界点前总共要缴的税收 const double BASE2=BASE1+(BREAK2-BREAK1 ...

  9. go 开发环境安装教程 windows

         首先进入go 语言官网下载最新安装包,我目前安装的版本是 1.8.3版本:go1.8.3.windows-amd64.msi 如果下载慢,这个是百度云地址:https://pan.baidu ...

  10. JMeter之Http协议接口性能测试

    一.不同角色眼中的接口 1.1,开发人员眼中的接口    1.2,测试人员眼中的接口 二.Http协议基本介绍 2.1,常见的接口协议 1.:2. :3. :4.:5.: 6. 2.2,Http协议栈 ...