(24)ASP.NET Core EF查询(查询的工作原理、跟踪与非跟踪查询)
1.查询生命周期
在进入正题时候,我们先来了解EF Core查询的生命周期。
1.1LINQ查询会由Entity Framework Core处理并生成给数据库提供程序可处理的表示形式(说白了就是生成给数据库可识别数据形式)。
●发送的查询结果(查询表示形式)会被缓存,以便每次执行查询时无需进行1.1中处理。
1.2查询结果(查询表示形式)会传递到数据库提供程序
●数据库提供程序会识别出查询的哪些部分可以在数据库中求值。
●查询的这些部分会转换为特定数据库的查询语言(例如,关系数据库的T-SQL)。
●一个或多个查询会发送到数据库并返回结果集(返回的是数据库中的值,而不是实体实例中的)。
1.3对于结果集中的每一项
1.3.1如果这是跟踪查询(后续会讲到),EF会检查数据是否表示已在上下文实例的更改跟踪器中的实体中。
●如果是,则会返回现有实体。
●如果不是,则会创建新实体、设置更改跟踪并返回该新实体。
1.3.2如果这是非跟踪查询(后续会讲到),EF会检查数据是否表示已在此查询的结果集中的实体中。
●如果是,则会返回现有实体。非跟踪查询使用弱引用跟踪已返回的实体。如果具有相同标识的上一个结果超出范围,并运行垃圾回收,则可能会获得新的实体实例。
●如果不是,则会创建新实体并返回该新实体。
1.4执行查询时
当调用LINQ运算符时,只会生成查询的内存中表示形式。当我们使用查询结果(查询表示形式)时才会发送到数据库。导致查询发送到数据库的最常见操作如下:
●在for循环中循环访问结果:
var blogs = from b in _context.Blog
select new
{
b.BlogId,
b.Url
};
//触发数据库查询
foreach(var blog in blogs)
{
var id = blog.BlogId;
}
当我们执行完LINQ运算符的时候,从SQL Server Profiler监控里面可以看到,并没有执行的SQL语句,也就是说查询结果blogs并没有立即发送给数据库获取返回数据结果集。
而当我们调试进去for循环时候,SQL Server Profiler监控里面可以看到出现了执行SQL语句。也就是说这时候查询结果blogs才执行发送给数据库返回结果集。
●使用ToList、ToArray、Single、Count等运算符
_context.Blog.ToList();
_context.Blog.ToArray();
_context.Blog.Count();
_context.Blog.Single();
_context.Blog.First();
执行这种形式运算符也会立即发送到数据库获取结果集的。具体执行过程呈现,这里大伙自行测试吧。
●将查询结果数据绑定到UI
2.跟踪查询与非跟踪查询
在1小节生命周期里面我们有提及过跟踪与非跟踪查询,现在我们来了解下这两种查询区别。
2.1跟踪查询
返回实体类型的查询是默认会被跟踪的,这表示如果这些实体实例有更改行为,会通过SaveChanges()持久化将更改的值更新到数据库中,但是如果更改的值跟实体实例的值相同,则不会持久化提交数据到数据库,这就是跟踪查询。在以下示例中,将检测到对博客链接所做的更改,并在 SaveChanges() 期间将这些更改持久化到数据库中。
//返回blog实体类型的查询是默认会被跟踪
var blog = _context.Blog.SingleOrDefault(b => b.BlogId == );
//检测对博客链接所做的更改
blog.Url = "";
//持久化保存到数据库中
_context.SaveChanges();
实体初始链接值是1,当我们点击Save按钮保存的时候,检测到对博客链接所做的更改值还是1的时候,并不会提交更改值到数据库中的。看看下图SQL Server Profiler监控就知道,并没有监控到对应有更新的T-SQL语句,也就是说并没有执行更新操作:
当我们再把链接值更改为2点击保存时候,EF Core检测到博客链接值已经从1更改为2,就会持久化保存到数据库中。
blog.Url = "";
废话少说,直接上图:
2.2非跟踪查询
如果不需要更新从数据库中检索到的实体,则应使用非跟踪查询。可以将单个查询替换为非跟踪查询。
var blogs = context.Blogs
//不用跟踪查询
.AsNoTracking()
.ToList();
//或者在上下文实例级别更改默认跟踪行为
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
var blogs = context.Blogs.ToList();
还是一样老谭秘方事例,当你加上非跟踪查询标识后,无论怎么更改博客链接值,都不会持久化保存数据到数据库中的。
var blogs = _context.Blog
//不用跟踪查询
.AsNoTracking()
.SingleOrDefault(m => m.BlogId == );
blogs.Url = "";
_context.SaveChanges();
直接上图跟踪结果:
在这相信大家从该小节跟踪与非跟踪查询中事例描述中总算对1小节查询生命周期有一定理解吧。
2.3跟踪和自定义投影
即使查询的结果类型不是实体类型,默认情况下EF Core也会跟踪结果中包含的实体类型。在以下返回匿名类型的查询中,结果集中的Blog实例会被跟踪。
var blog = context.Blogs
.Select(b =>
new
{
Blog = b,
PostCount = b.Posts.Count()
});
如果结果集包含来自LINQ组合的实体类型,EF Core将跟踪它们。
var blog = context.Blogs
.Select(b =>
new
{
Blog = b,
Post = b.Posts.OrderBy(p => p.Rating).LastOrDefault()
});
如果结果集不包含任何实体类型,则不会执行跟踪。在以下查询中,我们返回匿名类型(具有实体中的某些值,但没有实际实体类型的实例)。查询中没有任何被跟踪的实体。
var blog = context.Blogs
.Select(b =>
new
{
Id = b.BlogId,
Url = b.Url
});
EF Core支持执行顶级投影中的客户端评估。如果EF Core具体化实体实例以进行客户端评估,则会跟踪该实体实例。此处,由于我们要将blog实体传递到客户端方法StandardizeURL,因此EF Core也会跟踪博客实例。
var blogs = context.Blogs
.OrderByDescending(blog => blog.Rating)
.Select(blog => new
{
Id = blog.BlogId,
Url = StandardizeUrl(blog)
})
.ToList();
public static string StandardizeUrl(Blog blog)
{
var url = blog.Url.ToLower();
if (!url.StartsWith("http://"))
{
url = string.Concat("http://", url);
}
return url;
}
EF Core不会跟踪结果中包含的无键实体实例。但EF Core会根据上述规则跟踪带有键的实体类型的所有其他实例。
(24)ASP.NET Core EF查询(查询的工作原理、跟踪与非跟踪查询)的更多相关文章
- asp.net core+ef core
asp.net core+ef core 官方的文档https://docs.asp.net/en/latest/tutorials/first-mvc-app/start-mvc.html 先来看一 ...
- C#无限极分类树-创建-排序-读取 用Asp.Net Core+EF实现之方法二:加入缓存机制
在上一篇文章中我用递归方法实现了管理菜单,在上一节我也提到要考虑用缓存,也算是学习一下.Net Core的缓存机制. 关于.Net Core的缓存,官方有三种实现: 1.In Memory Cachi ...
- Asp.net Core + EF Core + Bootstrap搭建的MVC后台通用管理系统模板(跨平台版本)
Asp.net Core + EF Core + Bootstrap搭建的MVC后台通用管理系统模板(跨平台版本) 原创 2016年07月22日 10:33:51 23125 6月随着.NET COR ...
- ASP.NET Core EF 查询获取导航属性值,使用Include封装
// 引用 using Microsoft.EntityFrameworkCore; // 摘要: // Specifies related entities to include in the qu ...
- (25)ASP.NET Core EF查询(复杂查询运算符、原生SQL查询、异步查询)
1.复杂查询运算符 在生产场景中,我们经常用到LINQ运算符进行查询获取数据,现在我们就来了解下生产场景经常出现几种复杂查询运算符. 1.1联接(INNER JOIN) 借助LINQ Join运算符, ...
- 快读《ASP.NET Core技术内幕与项目实战》EFCore2.5:集合查询原理揭秘(IQueryable和IEnumerable)
本节内容,涉及4.6(P116-P130).主要NuGet包:如前述章节 一.LINQ和EFCore的集合查询扩展方法的区别 1.LINQ和EFCore中的集合查询扩展方法,虽然命名和使用完全一样,都 ...
- C#无限极分类树-创建-排序-读取 用Asp.Net Core+EF实现
今天做一个管理后台菜单,想着要用无限极分类,记得园子里还是什么地方见过这种写法,可今天找了半天也没找到,没办法静下心来自己写了: 首先创建节点类(我给它取名:AdminUserTree): /// & ...
- ASP.NET Core&EF 笔记
首先创建Asp.net Core项目,然后通过 NuGet 安装 EntityFrameworkCore: Microsoft.EntityFrameworkCore.SqlServer Micros ...
- (17)ASP.NET Core EF基于数据模型创建数据库
1.简介 使用Entity Framework Core构建执行基本数据访问的ASP.NET Core MVC应用程序.使用迁移(Migrations)基于数据模型创建数据库,你可以在Windows上 ...
随机推荐
- 死磕 java线程系列之线程模型
问题 (1)线程类型有哪些? (2)线程模型有哪些? (3)各语言使用的是哪种线程模型? 简介 在Java中,我们平时所说的并发编程.多线程.共享资源等概念都是与线程相关的,这里所说的线程实际上应该叫 ...
- Kubernetes 系列(六):Kubernetes部署Prometheus监控
1.创建命名空间 新建一个yaml文件命名为monitor-namespace.yaml,写入如下内容: apiVersion: v1 kind: Namespace metadata: name: ...
- MySQL数据库从复制及企业配置实践
在实际生产中,数据的重要性不言而喻: 如果我们的数据库只有一台服务器,那么很容易产生单点故障的问题,比如这台服务器访问压力过大而没有响应或者奔溃,那么服务就不可用了,再比如这台服务器的硬盘坏了,那么整 ...
- css 实现图片灰度
先看效果鼠标移入图片中摁下向左移动 图片由灰度变为原图 向右移动原图变灰度 代码如下:尚未做优化 <style> *{ margin:0; padding:0; } #img{ w ...
- 夯实Java基础系列22:一文读懂Java序列化和反序列化
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...
- [WP8.1]给Pivot的Header加上颜色
先上个效果图 以前想实现这个给Pivot加颜色时只找到8的,通过参考8的实现方式,8.1的实现如下,在Pivot的样式上做一些修改,如下图的红框处 另外如果要改Pivot的Header里文字的颜色又要 ...
- ELK 学习笔记之 elasticsearch环境搭建
ELK概述: ElasticSearch是个开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等 Logstash是一 ...
- Spring MVC拦截器学习
1 介绍 Spring Web MVC是基于Servlet API构建的原始Web框架. 2 拦截器 2.1 定义 springmvc框架的一种拦截机制 2.2 使用 2.2.1 两步走 实现Hand ...
- 想转行做程序员,目前想学WEB前端,想问该自学还是报培训班
首先我们还是先看一下WEB前端目前的工资情况吧,我在IT招聘网站拉勾网来进行搜索1-3年WEB前端工作经验大专学历的条件来看. 深圳: 可以看出目前深圳的平均的工资都在10K以上,因为大城市给的机会多 ...
- 10个比较流行的JavaScript面试题
1.如何理解 JS 中的this关键字? JS 初学者总是对this关键字感到困惑,因为与其他现代编程语言相比,JS 中的这this关键字有点棘手. “this” 一般是表示当前所在的对象,但是事情并 ...