了解 .NET Core 中急切加载和延迟加载的区别和优点。了解如何使用 Entity Framework Core 实现它们并优化数据访问。
预加载是一种用于在单个查询中从数据库检索相关或关联数据的技术。它的目的是通过一次性检索所有必要的信息来最大限度地减少获取数据所需的数据库往返次数。在 .NET Core 中,在处理涉及多个互连实体或表的复杂数据模型时,预加载尤其有用。
考虑这样一个场景,我们有两个实体,例如作者和书籍,其中每个作者可以有多个与其关联的书籍条目。预加载使我们能够在单个查询中获取作者及其相关书籍,从而优化性能并减少不必要的数据库访问。
让我们探索 Entity Framework Core 中的预加载功能。假设我们在 .NET Core 应用程序中定义了以下实体。
public class Author
{
public int AuthorId { get; set; }
public string Name { get; set; }
public ICollection<Book> Books { get; set; }
}
public class Book
{
public int BookId { get; set; }
public string Title { get; set; }
public int AuthorId { get; set; }
public Author Author { get; set; }
}
这里,Author类有一个Book对象的集合,建立了一对多的关系。
要使用 EF Core 执行预先加载,我们可以使用 Include 方法来指定应与主实体一起获取的相关实体。这是一个立即加载的示例。
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
public class MyDbContext : DbContext
{
public DbSet<Author> Authors { get; set; }
public DbSet<Book> Books { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("YourConnectionString");
}
}
class Program
{
static void Main(string[] args)
{
using (var context = new MyDbContext())
{
var authorsWithBooks = context.Authors
.Include(author => author.Books)
.ToList();
foreach (var author in authorsWithBooks)
{
Console.WriteLine($"Author: {author.Name}");
foreach (var book in author.Books)
{
Console.WriteLine($"- Book: {book.Title}");
}
}
}
}
}
在此示例中,查询中的 Include(author =>author.Books) 指示在获取作者时,EF Core 还应该加载其关联的书籍。这确保了当查询authorsWithBooks时,在单个数据库查询中获取每个作者的相关书籍。
延迟加载用于通过推迟某些资源或数据的加载直到特别需要它们来增强性能。这种方法通过仅加载当前操作所需的基本组件而不是预先加载所有资源来优化应用程序速度和内存使用。
假设我们有一个数据库上下文类 AppDbContext 和两个实体:Author 和 Book。 Book 实体有一个引用作者的导航属性。
public class Author
{
public int Id { get; set; }
public string Name { 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; }
}
public class AppDbContext : DbContext
{
public DbSet<Book> Books { get; set; }
public DbSet<Author> Authors { get; set; }
// Other configurations...
}
在这种情况下,如果我们检索书籍列表,我们可能不一定立即需要相应的作者信息。延迟加载允许我们仅在显式访问 Author 实体时才加载它。
using (var context = new AppDbContext())
{
var books = context.Books.ToList(); // Retrieves list of books
foreach (var book in books)
{
Console.WriteLine($"Book Title: {book.Title}");
Console.WriteLine($"Author: {book.Author.Name}"); // Lazy loading
}
}
在上面的代码中,当访问 book.Author.Name 时,Entity Framework Core 将延迟加载与每本书关联的 Author 实体。仅当访问 Author 属性时,它才会触发单独的数据库查询。
确保已安装 NuGet 包:Install-Package Microsoft.EntityFrameworkCore.Proxies。
默认情况下,Entity Framework Core 中未启用延迟加载,以防止因无意延迟加载整个对象图而导致意外性能下降。要显式启用延迟加载,我们可以通过重写 OnConfiguring 方法或在 Program.cs 中配置它(如果您使用依赖注入)来使用 DbContext 配置中的 UseLazyLoadingProxies 方法。
选项 1。 重写 DbContext 中的 OnConfiguring 方法。
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseLazyLoadingProxies();
}
选项 2:在 Program.cs 中使用依赖注入:
builder.Services.AddDbContext<YourDbContext>(options =>
{
options.UseLazyLoadingProxies();
options.UseSqlServer(builder.Configuration.GetConnectionString("YourConnectionString"));
});
急切加载和延迟加载之间的主要区别
急切加载和延迟加载之间的选择取决于特定的用例和性能考虑。当相关数据始终需要在一起时,预加载适用,通过减少后续查询来优化性能。另一方面,延迟加载适合最小化初始数据检索至关重要或并不总是需要关联数据的场景。