延迟加载是指在访问导航属性时,Entity Framework 会自动查询数据库并加载相关数据。这种方式在我们需要访问导航属性时比较方便,因为我们无需手动加载相关数据,而且只会在需要时才会进行查询,从而减少了不必要的开销。但是,如果我们需要访问多个导航属性,就可能会产生 N+1 问题,即需要执行多次查询来获取相关数据,从而影响性能。
及早加载是指在查询主实体时,同时加载其关联实体,以避免 N+1 问题。这种方式需要使用 Include 方法来指定需要加载的导航属性,可以通过链式调用来指定多个导航属性。及早加载可以提高查询性能,但是也会增加数据传输量,因为可能会一次性加载大量数据。
显式加载是指在需要时手动加载导航属性,适用于在已经查询到主实体的情况下,需要加载其关联实体的场景。这种方式需要使用 Load 方法来加载导航属性,可以使用 Collection 方法或者 Reference 方法来指定需要加载的导航属性。显式加载可以提高查询性能,因为只会查询需要的数据,但是需要手动编写代码来实现。
先下载项目中安装 Entity Framework NuGet 包和Microsoft.EntityFrameworkCore.InMemory包
,不连接数据库。
public class Author
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Book> Books { get; set; }
}
public class Book
{
public int Id { get; set; }
public string Title { get; set; }
public int AuthorId { get; set; }
public Author Author { get; set; }
}
创建数据库上下文类 LibraryContext,LibraryContext 继承DbContext类
DbContext 是 Entity Framework 核心 API 之一,它表示应用程序与数据库之间的会话和操作。通过继承 DbContext 类,我们可以创建一个自定义的数据库上下文类,并在该类中定义数据集合(DbSet)和其他相关信息,以便进行查询、插入、更新和删除数据等一系列操作。
public class LibraryContext : DbContext
{
public DbSet<Author> Authors { get; set; }
public DbSet<Book> Books { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseInMemoryDatabase("Library"); // 使用内存数据库
//
optionsBuilder.UseSqlServer("Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=Library;Integrated Security=True;");
}
}
static void Main(string[] args)
{
using (var context = new LibraryContext())
{
// 创建模拟数据
var author1 = new Author { Id = 1, Name = "Author 1" };
var author2 = new Author { Id = 2, Name = "Author 2" };
var book1 = new Book { Id = 1, Title = "Book 1", AuthorId = 1, Author = author1 };
var book2 = new Book { Id = 2, Title = "Book 2", AuthorId = 1, Author = author1 };
var book3 = new Book { Id = 3, Title = "Book 3", AuthorId = 2, Author = author2 };
// 将模拟数据添加到数据库
context.Authors.AddRange(new List<Author> { author1, author2 });
context.Books.AddRange(new List<Book> { book1, book2, book3 });
context.SaveChanges();
// 延迟加载
var loadedAuthor = context.Authors.FirstOrDefault(a => a.Id == 1);
var books = loadedAuthor.Books.ToList();
Console.WriteLine($"Author Name: {loadedAuthor.Name}");
foreach (var book in books)
{
Console.WriteLine($"Book Title: {book.Title}");
}
// 及早加载
var eagerLoadedAuthor = context.Authors.Include(a => a.Books).FirstOrDefault(a => a.Id == 2);
var eagerLoadedBooks = eagerLoadedAuthor.Books.ToList();
Console.WriteLine($"Author Name: {eagerLoadedAuthor.Name}");
foreach (var book in eagerLoadedBooks)
{
Console.WriteLine($"Book Title: {book.Title}");
}
// 显式加载
var explicitLoadedAuthor = context.Authors.FirstOrDefault(a => a.Id == 1);
context.Entry(explicitLoadedAuthor).Collection(a => a.Books).Load();
Console.WriteLine($"Author Name: {explicitLoadedAuthor.Name}");
foreach (var book in explicitLoadedAuthor.Books)
{
Console.WriteLine($"Book Title: {book.Title}");
}
}
Console.ReadLine();
}