加载相关对象

预加载(EagerlyLoading)

预加载表示在查询某类实体时一起加载相关实体,这是使用Include方法完成的,如下:

using(var context = newBloggingContext())

{

  // Load all blogsand related posts

  var blogs1 =context.Blogs

.Include(b=> b.Posts)

.ToList();

 

  // Load one blogsand its related posts

  var blog1 =context.Blogs

.Where(b=> b.Name == "ADO.NET Blog")

.Include(b=> b.Posts)

.FirstOrDefault();

 

  // Load all blogsand related posts 

  // using a stringto specify the relationship

  var blogs2 =context.Blogs

                        .Include("Posts")

                        .ToList();

 

  // Load one blogand its related posts 

  // using a stringto specify the relationship

  var blog2 =context.Blogs

                      .Where(b => b.Name == "ADO.NET Blog")

                      .Include("Posts")

                      .FirstOrDefault();

}

注意:Include方法是一个扩展方法,在System.Data.Entity命名空间下,确保引用了此命名空间。

多级预加载

下面的代码显示了如何加载多级实体。

using(var context = newBloggingContext())

{

  // Load all blogs,all related posts, and all related comments

  var blogs1 =context.Blogs

                     .Include(b =>b.Posts.Select(p => p.Comments))

                     .ToList();

 

  // Load all userstheir related profiles, and related avatar

  var users1 =context.Users

                      .Include(u =>u.Profile.Avatar)

                      .ToList();

 

  // Load all blogs,all related posts, and all related comments 

  // using a stringto specify the relationships

  var blogs2 =context.Blogs

                     .Include("Posts.Comments")

                     .ToList();

 

  // Load all userstheir related profiles, and related avatar 

  // using a stringto specify the relationships

  var users2 =context.Users

                      .Include("Profile.Avatar")

                      .ToList();

}

当前不支持在关联实体上进行查询,Include方法总是加载所有关联实体。

惰性加载

惰性加载指的是当第一访问导航属性的时候自动从数据库加载相关实体。这种特性是由代理类实现的,代理类派生自实体类,并重写了导航属性。所以我们的实体类的导航属性就必须标记为virtual,如下:

public class  Blog

{

  public int ID { get; set; }

  public string Title { get; set; }

  public virtual ICollection<Post>Posts { get; set;}

}

可以对指定实体关闭惰性加载,如下:

public class  Blog

{

  public int ID { get; set; }

  public string Title { get; set; }

  public ICollection<Post>Posts { get; set;}

}

也可以对所有实体关闭惰性加载,如下:

public class  BloggingContext: DbContext

{

  public BloggingContext()

  {

    this.Configuration.LazyLoadingEnabled=  false;

  }

}
public class BloggingContext: DbContext {
    publicBloggingContext() {
        this.Configuration.LazyLoadingEnabled = false;
    }
}

显式加载

即使关闭了惰性加载,我们仍然可以通过显式调用来延迟加载相关实体,这是通过调用DbEntityEntry上的相关方法做到的,如下:

using(var context = newBloggingContext())

{

  var post =context.Posts.Find(2);

 

  // Load the blogrelated to a given post

  context.Entry(post).Reference(p => p.Blog).Load();

 

  // Load the blogrelated to a given post using a string 

  context.Entry(post).Reference("Blog").Load();

 

  var blog =context.Blogs.Find(1);

 

  // Load the postsrelated to a given blog

  context.Entry(blog).Collection(p =>p.Posts).Load();

 

  // Load the postsrelated to a given blog 

  // using a stringto specify the relationship

  context.Entry(blog).Collection("Posts").Load();

}

注意:在外键关联中,加载依赖对象的相关端时,将根据内存中当前的相关外键值加载相关对象:

// Get thecourse where currently DepartmentID = 1.

Course course2 =context.Courses.First(c=>c.DepartmentID == 2);

 // UseDepartmentID foreign key property 

// to change theassociation.

course2.DepartmentID = 3;

 // Load therelated Department where DepartmentID = 3

context.Entry(course).Reference(c=> c.Department).Load();

在独立关联中,基于当前数据库中的外键值查询依赖对象的相关端。不过,如果修改了关系,并且依赖对象的引用属性指向对象上下文中加载的不同主对象,实体框架将尝试创建关系,就像它在客户端定义的那样。

Query方法提供了在加载相关实体的时候应用过滤条件的功能,引用导航属和集合导航属性都支持Query方法,但是大部分情况下都会针对集合导航属性使用Query方法,达到只加载部分相关实体的功能,如下:

using(var context = newBloggingContext())

{

  var blog =context.Blogs.Find(1);

 

  // Load the postswith the 'entity-framework' tag related to a given blog

  context.Entry(blog)

      .Collection(b => b.Posts)

      .Query()

      .Where(p => p.Title.Contains("entity-framework"))

      .Load();

 

  // Load the postswith the 'entity-framework' tag related to a given blog 

  // using a stringto specify the relationship  

  context.Entry(blog)

      .Collection("Posts")

      .Query()

      .Cast<Post>()

      .Where(p => p.Title.Contains("entity-framework"))

      .Load();

}

注意,使用显式加载的时候,最好关闭惰性加载,避免引起混乱。Load方法是一个扩展方法,记得引用命名空间System.Data.Entity.DbExtensions

使用Query查询相关实体个数,而不用加载相关实体,如下:

using(var context = newBloggingContext())
{

  var blog =context.Blogs.Find(1);

 

  // Count how manyposts the blog has 

  var postCount= context.Entry(blog)

                        .Collection(b =>b.Posts)

                        .Query()

                        .Count();

}