EntityFramework Core 2.0 Explicitly Compiled Query(显式编译查询)
前言
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(显式编译查询)的更多相关文章
- EntityFramework Core 2.0执行原始查询如何防止SQL注入?
前言 接下来一段时间我们来讲讲EntityFramework Core基础,精简的内容,深入浅出,希望为想学习EntityFramework Core的童鞋提供一点帮助. EntityFramewor ...
- EntityFramework Core 2.0全局过滤(HasQueryFilter)
前言 EntityFramework Core每一次版本的迭代和更新都会带给我们惊喜,每次都会尽量满足大部分使用者的需求.在EF Core 2.0版本中出现了全局过滤新特性即HasQueryFilte ...
- .NetCore技术研究-EntityFramework Core 3.0 Preview
前段时间.Net Core 3.0 发布了,Entity Framework Core 3.0 也发布了Preview版.假期用了一上午大致研究了一遍,同时又体验了一把Visual Studio 20 ...
- EntityFramework Core 2.0自定义标量函数两种方式
前言 上一节我们讲完原始查询如何防止SQL注入问题同时并提供了几种方式.本节我们继续来讲讲EF Core 2.0中的新特性自定义标量函数. 自定义标量函数两种方式 在EF Core 2.0中我们可以将 ...
- EntityFramework Core 3.0查询
前言 随着.NET Core 3.0的发布,EF Core 3.0也随之正式发布,关于这一块最近一段时间也没太多去关注,陆续会去对比之前版本有什么变化没有,本节我们来看下两个查询. 分组 我们知道在E ...
- CSS3 Media Query 响应式媒体查询
在CSS中,有一个极其实用的功能:@media 响应式布局.具体来说,就是可以根据客户端的介质和屏幕大小,提供不同的样式表或者只展示样式表中的一部分.通过响应式布局,可以达到只使用单一文件提供多平台的 ...
- Entity Framework Core 2.0 新特性
本文翻译来自:https://docs.microsoft.com/en-us/ef/core/what-is-new/index 一.模型级查询过滤器(Model-level query filte ...
- 《你必须掌握的Entity Framework 6.x与Core 2.0》书籍出版
前言 到目前为止写过刚好两百来篇博客,看过我博客的读者应该大概知道我每一篇博客都沿袭着一贯的套路,从前言到话题最终到总结,本文依然是一如既往的套路,但是不是介绍技术,也可说是介绍技术,不过是介绍书中的 ...
- .Net Core 2.0生态(4):Entity Framework Core 2.0 特性介绍和使用指南
前言 这是.Net Core 2.0生态生态介绍的最后一篇,EF一直是我喜欢的一个ORM框架,随着版本升级EF也发展到EF6.x,Entity Framework Core是一个支持跨平台的全新版本, ...
随机推荐
- BZOJ 3895: 取石子[SG函数 搜索]
有N堆石子 ·从某堆石子中取走一个 ·合并任意两堆石子 不能操作的人输. 100%的数据满足T<=100, N<=50. ai<=1000 容易发现基础操作数$d=\sum a ...
- 如何使用 Bootstrap 搭建更合理的 HTML 结构
前言 Bootstrap 的成功不仅在于其简单易用,更在于其样式的规范性以及 HTML 结构的合理性.但是很多人在使用 Bootstrap 时只是依照文档盲目的复制黏贴,并没有仔细考虑每个类的用处,也 ...
- python中的string
也可以用一个变量来保存字符串,然后输出str = ‘bad’print str 如果你想表示一段带有英文单引号或者双引号的文字,那么表示这个字符串的引号就要与内容区别开. 内容带有单引号,就用双引号表 ...
- 零基础2018如何系统地学习python?
首先告诉你的是,零基础学习开始系统学习Python肯定难,Python的专业程度本身就不简单,学习这事本来就是一件非常煎熬的事情,人都不愿意学习,可是没办法,为了生存掌握一个技能,你必须学,如果你认真 ...
- FastDFS + Nginx 安装
1.安装FastDFS依赖lib包 cd /usr/local/src/ git clone https://github.com/happyfish100/libfastcommon.git cd ...
- .addClass(),.removeClass(),.toggleClass()的区别
.addClass("className")方法是用来给指定元素增加类名,也就是说给指定的元素追加样式: 可以同时添加多个类名,空格符隔开 $("selector&quo ...
- xBIM WeXplorer 设置模型颜色
目录 基础 xBIM WeXplorer 简要介绍 xBIM WeXplorer xViewer 基本应用 xBIM WeXplorer xViewer 浏览器检查 xBIM WeXplorer xV ...
- qdoc.exe
qdoc.exe Usage: qdoc [options] file1.qdocconf ... # Qt文档生成器 Qt documentation generator # 设置 Options: ...
- Qt ActiveX web dome 详细例子
http://doc.qt.io/qt-5.9/activeqt-server.html hierarchy 例子 #ifndef OBJECTS_H #define OBJECTS_H #inclu ...
- NOIP2017记
Day-1~Day0 帮忙布置考场,打印座位表耗掉了不少XFZ的白纸(被瞪了一眼),围着三四楼跑了不知道多少圈贴座位表,跑到绝望...... 然后试了一下机,性能还可以,但是大佬用的机的cpu都不是很 ...