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 ...
随机推荐
- 转:每天一个linux命令(1):ls命令
ls命令是linux下最常用的命令.ls命令就是list的缩写缺省下ls用来打印出当前目录的清单如果ls指定其他目录那么就会显示指定目录里的文件及文件夹清单. 通过ls 命令不仅可以查看linu ...
- @Autowired和@Resource的区别是什么?
@Autowired 与@Resource: 1.@Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上. 2.@Autowired默认按类型装配 ...
- python+selenium自动化软件测试(第2章):WebDriver API
2.1 操作元素基本方法 前言前面已经把环境搭建好了,从这篇开始,正式学习selenium的webdriver框架.我们平常说的 selenium自动化,其实它并不是类似于QTP之类的有GUI界面的可 ...
- Django配置mysql
我的环境为windows10+pyhton3.6+Django1.11.4 由于mysqldb不支持python3,所以django连接MySQL就不能再使用mysqldb了.故而选择了mysqlcl ...
- 原创 :nfs软件服务利用ansible实现一键化部署
[root@m01 tools]# cat nfspeizhi.shcat >>/etc/exports<<EOF /data 172.16.1.0/24(rw,sync)EO ...
- mysql:ip地址连接
2. 为用户授权 授权格式:grant 权限 on 数据库.* to 用户名@登录主机 identified by "密码"; 2.1登录MYSQL(有ROOT权限),这里以ROO ...
- Google的SPDY协议成为HTTP 2.0的基础
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt384 据TNW援引 IFTF HTTP 工作组主席 Mark Notting ...
- java.lang.ClassNotFoundException: com.sun.jna.Native
在使用sprng boot加elasticsearch的时候遇到 java.lang.ClassNotFoundException: com.sun.jna.Native,百度之后要我导入 <d ...
- 线性表之何时使用ArrayList、LinkedList?
前言 线性表不仅可以存储重复的元素,而且可以指定元素存储的位置并根据下表访问元素. List接口的两个具体实现:数组线性表类ArrayList.链表类LinkedList. ArrayList Arr ...
- Kendo UI 使用小知识点汇总
本攻略适用于了解的kendo UI 的基本语法的人使用.如果还不了解Kendo UI的基本语法,请大力观摹Demo ,并自己动用写几个控件. 1.获取Kendo UI的控件实体,不必存成全局变量. ...