EntityFramework

Eagerly Loading

Eager loading is the process whereby a query for one type of entity also loads related entities as part of the query. Eager loading is achieved by use of the Include method. For example, the queries below will load blogs and all the posts related to each blog.

  1. using (var context = new BloggingContext())
  2. {
  3. // Load all blogs and related posts
  4. var blogs1 = context.Blogs
  5. .Include(b => b.Posts)
  6. .ToList();
  7. // Load one blogs and its related posts
  8. var blog1 = context.Blogs
  9. .Where(b => b.Name == "ADO.NET Blog")
  10. .Include(b => b.Posts)
  11. .FirstOrDefault();
  12. // Load all blogs and related posts
  13. // using a string to specify the relationship
  14. var blogs2 = context.Blogs
  15. .Include("Posts")
  16. .ToList();
  17. // Load one blog and its related posts
  18. // using a string to specify the relationship
  19. var blog2 = context.Blogs
  20. .Where(b => b.Name == "ADO.NET Blog")
  21. .Include("Posts")
  22. .FirstOrDefault();
  23. }

Note that Include is an extension method in the System.Data.Entity namespace so make sure you are using that namespace.


Eagerly Loading multiple levels

It is also possible to eagerly load multiple levels of related entities. The queries below show examples of how to do this for both collection and reference navigation properties.

  1. using (var context = new BloggingContext())
  2. {
  3. // Load all blogs, all related posts, and all related comments
  4. var blogs1 = context.Blogs
  5. .Include(b => b.Posts.Select(p => p.Comments))
  6. .ToList();
  7. // Load all users their related profiles, and related avatar
  8. var users1 = context.Users
  9. .Include(u => u.Profile.Avatar)
  10. .ToList();
  11. // Load all blogs, all related posts, and all related comments
  12. // using a string to specify the relationships
  13. var blogs2 = context.Blogs
  14. .Include("Posts.Comments")
  15. .ToList();
  16. // Load all users their related profiles, and related avatar
  17. // using a string to specify the relationships
  18. var users2 = context.Users
  19. .Include("Profile.Avatar")
  20. .ToList();
  21. }

Note that it is not currently possible to filter which related entities are loaded. Include will always bring in all related entities.


Lazy Loading

Lazy loading is the process whereby an entity or collection of entities is automatically loaded from the database the first time that a property referring to the entity/entities is accessed. When using POCO entity types, lazy loading is achieved by creating instances of derived proxy types and then overriding virtual properties to add the loading hook. For example, when using the Blog entity class defined below, the related Posts will be loaded the first time the Posts navigation property is accessed:

  1. public class Blog
  2. {
  3. public int BlogId { get; set; }
  4. public string Name { get; set; }
  5. public string Url { get; set; }
  6. public string Tags { get; set; }
  7. public virtual ICollection<Post> Posts { get; set; }
  8. }

Turn lazy loading off for serialization

Lazy loading and serialization don’t mix well, and if you aren’t careful you can end up querying for your entire database just because lazy loading is enabled. Most serializers work by accessing each property on an instance of a type. Property access triggers lazy loading, so more entities get serialized. On those entities properties are accessed, and even more entities are loaded. It’s a good practice to turn lazy loading off before you serialize an entity. The following sections show how to do this.

Turning off lazy loading for specific navigation properties

Lazy loading of the Posts collection can be turned off by making the Posts property non-virtual:

  1. public class Blog
  2. {
  3. public int BlogId { get; set; }
  4. public string Name { get; set; }
  5. public string Url { get; set; }
  6. public string Tags { get; set; }
  7. public ICollection<Post> Posts { get; set; }
  8. }

Loading of the Posts collection can still be achieved using eager loading (see Eagerly Loading above) or the Load method (see Explicitly Loading below).

Turn off lazy loading for all entities

Lazy loading can be turned off for all entities in the context by setting a flag on the Configuration property. For example:

  1. public class BloggingContext : DbContext
  2. {
  3. public BloggingContext()
  4. {
  5. this.Configuration.LazyLoadingEnabled = false;
  6. }
  7. }

Loading of related entities can still be achieved using eager loading (see Eagerly Loading above) or the Load method (see Explicitly Loading below).


Explicitly Loading

Even with lazy loading disabled it is still possible to lazily load related entities, but it must be done with an explicit call. To do so you use the Load method on the related entity’s entry. For example:

  1. using (var context = new BloggingContext())
  2. {
  3. var post = context.Posts.Find(2);
  4. // Load the blog related to a given post
  5. context.Entry(post).Reference(p => p.Blog).Load();
  6. // Load the blog related to a given post using a string
  7. context.Entry(post).Reference("Blog").Load();
  8. var blog = context.Blogs.Find(1);
  9. // Load the posts related to a given blog
  10. context.Entry(blog).Collection(p => p.Posts).Load();
  11. // Load the posts related to a given blog
  12. // using a string to specify the relationship
  13. context.Entry(blog).Collection("Posts").Load();
  14. }

Note that the Reference method should be used when an entity has a navigation property to another single entity. On the other hand, the Collection method should be used when an entity has a navigation property to a collection of other entities.

Applying filters when explicitly loading related entities

The Query method provides access to the underlying query that the Entity Framework will use when loading related entities. You can then use LINQ to apply filters to the query before executing it with a call to a LINQ extension method such as ToList, Load, etc. The Query method can be used with both reference and collection navigation properties but is most useful for collections where it can be used to load only part of the collection. For example:

  1. using (var context = new BloggingContext())
  2. {
  3. var blog = context.Blogs.Find(1);
  4. // Load the posts with the 'entity-framework' tag related to a given blog
  5. context.Entry(blog)
  6. .Collection(b => b.Posts)
  7. .Query()
  8. .Where(p => p.Tags.Contains("entity-framework")
  9. .Load();
  10. // Load the posts with the 'entity-framework' tag related to a given blog
  11. // using a string to specify the relationship
  12. context.Entry(blog)
  13. .Collection("Posts")
  14. .Query()
  15. .Where(p => p.Tags.Contains("entity-framework")
  16. .Load();
  17. }

When using the Query method it is usually best to turn off lazy loading for the navigation property. This is because otherwise the entire collection may get loaded automatically by the lazy loading mechanism either before or after the filtered query has been executed.

Note that while the relationship can be specified as a string instead of a lambda expression, the returned IQueryable is not generic when a string is used and so the Cast method is usually needed before anything useful can be done with it.

Using Query to count related entities without loading them

Sometimes it is useful to know how many entities are related to another entity in the database without actually incurring the cost of loading all those entities. The Query method with the LINQ Count method can be used to do this. For example:

  1. using (var context = new BloggingContext())
  2. {
  3. var blog = context.Blogs.Find(1);
  4. // Count how many posts the blog has
  5. var postCount = context.Entry(blog)
  6. .Collection(b => b.Posts)
  7. .Query()
  8. .Count();
  9. }

EntityFramework.Core

Entity Framework Core allows you to use the navigation properties in your model to load related entities. There are three common O/RM patterns used to load related data.

  • Eager loading means that the related data is loaded from the database as part of the initial query.
  • Explicit loading means that the related data is explicitly loaded from the database at a later time.
  • Lazy loading means that the related data is transparently loaded from the database when the navigation property is accessed. Lazy loading is not yet possible with EF Core.

Eager Loading

You can use the Include method to specify related data to be included in query results. In the following example, the blogs that are returned in the results will have their Posts property populated with the related posts.

  1. using (var context = new BloggingContext())
  2. {
  3. var blogs = context.Blogs
  4. .Include(blog => blog.Posts)
  5. .ToList();
  6. }

Entity Framework Core will automatically fix-up navigation properties to any other entities that were previously loaded into the context instance. So even if you don't explicitly include the data for a navigation property, the property may still be populated if some or all of the related entities were previously loaded.

You can include related data from multiple relationships in a single query.

  1. using (var context = new BloggingContext())
  2. {
  3. var blogs = context.Blogs
  4. .Include(blog => blog.Posts)
  5. .Include(blog => blog.Owner)
  6. .ToList();
  7. }

Including multiple levels

You can drill down thru relationships to include multiple levels of related data using the ThenInclude method. The following example loads all blogs, their related posts, and the author of each post.

  1. using (var context = new BloggingContext())
  2. {
  3. var blogs = context.Blogs
  4. .Include(blog => blog.Posts)
  5. .ThenInclude(post => post.Author)
  6. .ToList();
  7. }

You can chain multiple calls to ThenInclude to continue including further levels of related data.

  1. using (var context = new BloggingContext())
  2. {
  3. var blogs = context.Blogs
  4. .Include(blog => blog.Posts)
  5. .ThenInclude(post => post.Author)
  6. .ThenInclude(author => author.Photo)
  7. .ToList();
  8. }

You can combine all of this to include related data from multiple levels and multiple roots in the same query.

  1. using (var context = new BloggingContext())
  2. {
  3. var blogs = context.Blogs
  4. .Include(blog => blog.Posts)
  5. .ThenInclude(post => post.Author)
  6. .ThenInclude(author => author.Photo)
  7. .Include(blog => blog.Owner)
  8. .ThenInclude(owner => owner.Photo)
  9. .ToList();
  10. }

Ignored includes

If you change the query so that it no longer returns instances of the entity type that the query began with, then the include operators are ignored.

In the following example, the include operators are based on the Blog, but then the Select operator is used to change the query to return an anonymous type. In this case, the include operators have no effect.

  1. using (var context = new BloggingContext())
  2. {
  3. var blogs = context.Blogs
  4. .Include(blog => blog.Posts)
  5. .Select(blog => new
  6. {
  7. Id = blog.BlogId,
  8. Url = blog.Url
  9. })
  10. .ToList();
  11. }

By default, EF Core will log a warning when include operators are ignored. See Logging for more information on viewing logging output. You can change the behavior when an include operator is ignored to either throw or do nothing. This is done when setting up the options for your context - typically in DbContext.OnConfiguring, or in Startup.cs if you are using ASP.NET Core.

  1. protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
  2. {
  3. optionsBuilder
  4. .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFQuerying;Trusted_Connection=True;")
  5. .ConfigureWarnings(warnings => warnings.Throw(CoreEventId.IncludeIgnoredWarning));
  6. }

Explicit loading

You can explicitly load a navigation property via the DbContext.Entry(...) API.

  1. using (var context = new BloggingContext())
  2. {
  3. var blog = context.Blogs
  4. .Single(b => b.BlogId == 1);
  5. context.Entry(blog)
  6. .Collection(b => b.Posts)
  7. .Load();
  8. context.Entry(blog)
  9. .Reference(b => b.Owner)
  10. .Load();
  11. }

Querying related entities

You can also get a LINQ query that represents the contents of a navigation property.

This allows you to do things such as running an aggregate operator over the related entities without loading them into memory.

  1. using (var context = new BloggingContext())
  2. {
  3. var blog = context.Blogs
  4. .Single(b => b.BlogId == 1);
  5. var postCount = context.Entry(blog)
  6. .Collection(b => b.Posts)
  7. .Query()
  8. .Count();
  9. }

You can also filter which related entities are loaded into memory.

  1. using (var context = new BloggingContext())
  2. {
  3. var blog = context.Blogs
  4. .Single(b => b.BlogId == 1);
  5. var goodPosts = context.Entry(blog)
  6. .Collection(b => b.Posts)
  7. .Query()
  8. .Where(p => p.Rating > 3)
  9. .ToList();
  10. }

Lazy Loading

Lazy loading is not yet supported by EF Core. You can view the lazy loading item on our backlog to track this feature.

Lazy Loading | Explicit Loading | Eager Loading in EntityFramework and EntityFramework.Core的更多相关文章

  1. Entity Framework加载相关实体——延迟加载Lazy Loading、贪婪加载Eager Loading、显示加载Explicit Loading

    Entity Framework提供了三种加载相关实体的方法:Lazy Loading,Eager Loading和Explicit Loading.首先我们先来看一下MSDN对三种加载实体方法的定义 ...

  2. EF Core 2.1 中的 Eager loading、Explicit loading和LazyLoading (转自MSDN)

    Entity Framework Core allows you to use the navigation properties in your model to load related enti ...

  3. Entity Framework Tutorial Basics(36):Eager Loading

    Eager Loading: Eager loading is the process whereby a query for one type of entity also loads relate ...

  4. EntityFramework 学习 一 Eager Loading

    贪婪加载是指查询一个类型实体的时候同时查询与实体关联的类型 通过Include()方法实现 using (var context = new SchoolDBEntities()) { var stu ...

  5. EF的预先加载--Eager Loading

    预先加载 在对一种类型的实体进行查询时,将相关的实体作为查询的一部分一起加载.预先加载可以使用Include()方法实现. 在此需要说明的是:EF中有两种表关联的方法,一种是Join()方法,一种是I ...

  6. vue axios配置 发起请求加载loading请求结束关闭loading

    axios带有请求拦截器,避免在每个请求里面加loading重复操作,可以封装进去,在请求开始时加载loading层,请求结束关闭,loading层用vux的loading加载 axios.js im ...

  7. Can you explain Lazy Loading?

    Introduction Lazy loading is a concept where we delay the loading of the object until the point wher ...

  8. EF 5 最佳实践白皮书

    Performance Considerations for Entity Framework 5 By David Obando, Eric Dettinger and others Publish ...

  9. java设计模式大全 Design pattern samples in Java(最经典最全的资料)

    java设计模式大全 Design pattern samples in Java(最经典最全的资料) 2015年06月19日 13:10:58 阅读数:11100 Design pattern sa ...

随机推荐

  1. Hive 报错:java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.metastore.HiveMetaStoreClient

    在配置好hive后启动报错信息如下: [walloce@bigdata-study- hive--cdh5.3.6]$ bin/hive Logging initialized using confi ...

  2. Struts2学习笔记四 OGNL

    OGNL,全称为Object-Graph Navigation Language(对象图表达语言),它是一个功能强大的表达式语言,用来获取和设置Java对象的属性,调用java对象的方法,同时能够自动 ...

  3. 【Spring源码深度解析学习系列】核心类介绍(一)

    一.DefaultListableBeanFactory 首先看一下结构 由图可知XmlBeanFactory继承自DefaultListableBeanFactory,而DefaultListabl ...

  4. 【django之权限组件】

    一.需求分析 RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联.简单地说,一个用户拥有若干角色,一个角色拥有若干权限.这样,就构造成& ...

  5. 2017-2018-1 20155214&20155216 实验四:外设驱动程序设计

    2017-2018-1 20155214&20155216 实验四:外设驱动程序设计 实验四外设驱动程序设计-1 实验要求: 学习资源中全课中的"hqyj.嵌入式Linux应用程序开 ...

  6. C语言博客作业--字符数组-陈张鑫

    一.PTA实验作业(4分) 题目1:7-5 查验身份证 1. 本题PTA提交列表(要提交列表,不是结果) 2. 设计思路(伪代码或流程图) 定义变量身份证个数n,合法个数count=0,flag=0, ...

  7. 学号:201621123032 《Java程序设计》第8周学习总结

    1:本周学习总结 2:书面作业 2.1:ArrayList代码分析 2.1.1:解释ArrayList的contains源代码 Contains方法调用indexof方法,如果元素为null,则循环比 ...

  8. 201621123031 《Java程序设计》第13周学习总结

    作业13-网络 1.本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 为你的系统增加网络功能(购物车.图书馆管理.斗地主等)-分组完成 为了让你的系统可以被 ...

  9. Markdown文本测试

    一级标题 二级标题 三级标题 四级标题 五级标题 六级标题 1. 这是一 2. 这是二 这是无序符号 My Github 这是着重表示 这是斜体 一级粗体 二级斜体 cin >> a; c ...

  10. ES6常用新特性

    https://segmentfault.com/a/1190000011976770?share_user=1030000010776722 该文章为转载文章!仅个人喜好收藏文章! 1.前言 前几天 ...