EntityFramework Core饥饿加载忽略导航属性问题
前言
.NET Core项目利用EntityFramework Core作为数据访问层一直在进行中,一直没有过多的去关注背后生成的SQL语句,然后老大捞出日志文件一看,恩,有问题了,所以本文产生了,也是有点疑惑,若有知情者,还望告知。
EntityFramework Core忽略导航属性
在前面我们已经探讨过利用Serilog日志框架来输出日志,所以对于本节查询日志的输出依然借助Seilog。我们在Startup.cs类中Starup方法中是创建日志实例。
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.RollingFile(Path.Combine(
env.ContentRootPath, "{Date}.log"))
.CreateLogger();
接着我们只需要将Serilog注入到日志管道中即可在Configure方法中注入。
loggerFactory.AddSerilog();
完成上述日志输出只需要安装如下三个包即可。
接下来记录日志只需要在控制器类或者其他类构造函数注入即可。
public class HomeController : Controller
{
private readonly ILogger _logger; private IBlogRepository _blogRepository;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
_blogRepository = blogRepository;
}
}
关于EntityFramework Core中映射等就不再阐述,请参看前面EntityFramework Core系列。下面我们直接给出查询操作
public async Task<IEnumerable<Post>> GetPosts()
{
var posts = await _context.Blogs
.AsNoTracking()
.Include(d => d.Posts)
.SelectMany(d => d.Posts)
.Select(p => new Post()
{
Id = p.Id,
Title = p.Title,
Content = p.Content
}).ToListAsync(); return await Task.FromResult(posts);
}
不必太纠结上述查询语句,当有多表查询时我们最终需要获取Blog中的Post,最终才有了上述语句。我们看到如下日志文件。
我们来查看其中生成的Linq语句。
继续往下看我们将看到如下语句:
2017-09-28 00:36:58.901 +08:00 [Warning] The Include operation for navigation: 'd.Posts' was ignored because the target navigation is not reachable in the final query results. To configure this warning use the DbContextOptionsBuilder.ConfigureWarnings API (event id 'CoreEventId.IncludeIgnoredWarning'). ConfigureWarnings can be used when overriding the DbContext.OnConfiguring method or using AddDbContext on the application service provider.
上述警告语句提示导航属性Posts被忽略了因为其未能到达最终的查询结果,但是最终我们还是能看到里面确确实实是有数据的。
然后查看EntityFramework Core官方文档已经说明了此情况何时发生。
当利用饥饿加载进行查询操作时,最终并未返回原实体的实例此时将忽略Include导航属性。但是上述最终还是返回了数据,这是不是就暗示着并未利用饥饿加载而是在内存中操作呢。然后通过SQL Profiler进行监控得知只生成了一条SQL语句。
到这里还是没明白官方文档中所叙述的忽略导航属性究竟是什么意思?如果忽略了导航属性上述利用Linq进行查询应该会出现异常才对或者不会进行内连接,不知所云。所以上述查询我们只能返回Blog,而非其他实体,例如如下:
public async Task<IEnumerable<Blog>> GetPosts()
{
var posts = await _context.Blogs
.AsNoTracking()
.Include(d => d.Posts)
.ToListAsync(); return await Task.FromResult(posts);
}
或者
public async Task<IEnumerable<Blog>> GetPosts()
{
var posts = await _context.Blogs
.AsNoTracking()
.Include(d => d.Posts)
.Select(b => b)
.ToListAsync(); return await Task.FromResult(posts);
}
通过在github上找到如下issue:【https://github.com/aspnet/EntityFrameworkCore/issues/7153】 文中所述在1.1版本中将优化这种查询,目前我所使用版本为1.1.2,既然能正确返回值为何还打印警告日志提醒呢,看来这并不是问题,虽然忽略了但是还是进行了优化查询能够正确查询出数据。
总结
该问题演示在EntityFramework Core 1.1.2版本中,既然给出了提示那么应该是未解决,如果未解决那么将出现性能问题,如果我们进行投影然后ToList,此时利用Include进行饥饿加载,但是Include却被忽略,此时将生成一条单个SQL语句来查询获取结果集中每个元素的导航属性。若Include未被忽略并按照我们设想进行表连接,此时性能会更好。文中日志记录显示Include被忽略,但是生成SQL语句没有问题,却还是输出日志警告提醒,这究竟是为何,郁闷?
EntityFramework Core饥饿加载忽略导航属性问题的更多相关文章
- ASP.NET MVC深入浅出(被替换) 第一节: 结合EF的本地缓存属性来介绍【EF增删改操作】的几种形式 第三节: EF调用普通SQL语句的两类封装(ExecuteSqlCommand和SqlQuery ) 第四节: EF调用存储过程的通用写法和DBFirst模式子类调用的特有写法 第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性) 第十节: EF的三种追踪
ASP.NET MVC深入浅出(被替换) 一. 谈情怀-ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态 ...
- 第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性)
一. 简介 上一个章节中,也介绍了立即加载和延迟加载,但上一个章节是针对单表而言的,不含外键,立即也好,延迟也好,都是指单表中的数据.但本章节重点介绍的三种加载方式均是针对含(导航属性.外键)的情况下 ...
- Orchard Module,Theme,Core扩展加载概述
Orchard 源码探索(Module,Theme,Core扩展加载概述) 参考: http://www.orchardch.com/Blog/20120830071458 1. host.Initi ...
- .Net Core·热加载的实现及测试
阅文时长 | 0.25分钟 字数统计 | 460字符 主要内容 | 1.引言&背景 2.解决原理&方法 3.声明与参考资料 『.Net Core·热加载的实现及测试』 编写人 | SC ...
- asp.net core重新加载应用配置
asp.net core重新加载应用配置 Intro 我把配置放在了数据库或者是Redis里,配置需要修改的时候我要直接修改数据库,然后调用一个接口去重新加载应用配置,于是就尝试写一个运行时重新加载配 ...
- 【Dojo 1.x】笔记7 配置对象dojoConfig的内容1:has属性、加载器的属性
说完了出身,即出身自dojo/_base/目录下的config模块,那就要好好讲讲这对象有什么可以写的属性了. 1. has属性 官方说是用于更好的特征检测的,具体有什么用现在还不得知. 例如: &l ...
- Entity Framework Core 懒加载
众所周知在EF 6 及以前的版本中,是支持懒加载(Lazy Loading)的,可惜在EF Core 并不支持,必须使用Include方法来支持导航属性的数据加载.不过现在EF Core的开发团队打算 ...
- spring-自动加载配置文件\使用属性文件注入
在上一篇jsf环境搭建的基础上 , 加入spring框架 , 先看下目录结构 src/main/resources 这个source folder 放置web项目所需的主要配置,打包时,会自动打包到W ...
- Orchard 源码探索(Module,Theme,Core扩展加载概述)
参考: http://www.orchardch.com/Blog/20120830071458 1. host.Initialize(); private static IOrchardHost H ...
随机推荐
- C语言指针详解
前言 这不是我第一次写关于C指针的文章了,只是因为指针对于C来说太重要,而且随着自己编程经历越多,对指针的理解越多,因此有了本文. 为什么需要指针? 指针解决了一些编程中基本的问题. 第一,指针的使用 ...
- struts2-请求参数校验
校验的分类 : 客户端数据校验 和 服务器端数据校验 客户端数据校验 ,通过JavaScript 完成校验 (改善用户体验,使用户减少出错 ) 服务器数据校验 ,使用框架内置校验功能 (struts2 ...
- ionic实战系列(二):使用cordova插件
本章主要关注cordova的各种插件,利用好手机(移动设备)的原生功能.首先cordova是一个将web网页内嵌到原生app的平台(核心功能),然后cordova拥有的插件系统扩展了核心功能. Cor ...
- JVM(一) OpenJDK1.8源码在Ubuntu16.04下的编译
笔者最近在学习周志明老师编写的<深入理解Java虚拟机>一书,书中第一章的实战部分就是"自己编译JDK",不过书中提到的是OpenJDK 7的编译.由于现在Java开发 ...
- Tornado模板
--------------------静态文件-------------------- 1.static_path:通过向web.Application类的构造函数传递一个名为static_path ...
- django框架简介
-------------------MVC与MVT框架-------------------1.MVC MVC框架的核心思想是:解耦.降低各功能模块之间的耦合性,方便将来变化时,更容易重构代码,最大 ...
- 优化关键渲染路径CRP
什么是关键渲染路径? 从收到 HTML.CSS 和 JavaScript 字节到对其进行必需的处理,从而将它们转变成渲染的像素这一过程中有一些中间步骤 浏览器渲染页面前需要先构建 DOM 和 CSSO ...
- 猜数字游戏--基于python
"""题目:练习使用python写一个猜数字的游戏,数字范围0-100,每次猜错,需要给出缩小后的范围,每个人只有10次的猜测机会,猜测机会用完游戏结束!"&q ...
- 垃圾收集器Serial 、Parallel、CMS、G1
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt378 这里介绍4个垃圾收集器,如果进行了错误的选择将会大大的影响程序的性能. ...
- 详解 anjularjs的ui-route(多视图、视图嵌套、视图传参)
最近整理了一下anjularjs的第三方插件ui-route,在这就以一个demo的形式讲解一下.整片博客均以开头的demo代码为例.下边是个目录,大家可以酌情直接跳转浏览. 1. demo的代码 2 ...