EF Core的查询延迟加载代理是一种在访问导航属性时才自动从数据库加载关联数据的机制,能减少不必要的数据库查询,提升数据访问效率。使用延迟加载代理需要先进行相关配置,再通过特定方式定义实体和查询数据。

启用延迟加载代理的前置条件
要使用EF Core的延迟加载代理,首先需要满足两个基础条件:
- 项目中安装EF Core的代理相关包,不同EF Core版本对应的包名称略有差异,较新版本通常使用
Microsoft.EntityFrameworkCore.Proxies包。 - 实体的导航属性必须是virtual的,这样代理类才能重写这些属性,实现延迟加载的逻辑。
启用延迟加载代理的配置步骤
第一步:安装依赖包
在项目的NuGet包管理器中搜索并安装Microsoft.EntityFrameworkCore.Proxies包,或者通过命令行执行安装命令:
dotnet add package Microsoft.EntityFrameworkCore.Proxies
第二步:配置DbContext启用代理
在DbContext的OnConfiguring方法中,调用UseLazyLoadingProxies方法启用延迟加载代理,示例代码如下:
using Microsoft.EntityFrameworkCore;
public class AppDbContext : DbContext
{
public DbSet<Order> Orders { get; set; }
public DbSet<OrderItem> OrderItems { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// 启用延迟加载代理,连接字符串替换为实际的项目配置
optionsBuilder.UseLazyLoadingProxies()
.UseSqlServer("Server=localhost;Database=TestDb;Trusted_Connection=True;");
}
}
第三步:定义支持延迟加载的实体
实体的导航属性必须标记为virtual,这样代理类才能重写该属性,以下是订单和订单项的实体示例:
public class Order
{
public int Id { get; set; }
public string OrderNo { get; set; }
// 导航属性标记为virtual,支持延迟加载
public virtual ICollection<OrderItem> Items { get; set; }
}
public class OrderItem
{
public int Id { get; set; }
public string ProductName { get; set; }
public int Quantity { get; set; }
public int OrderId { get; set; }
// 导航属性标记为virtual,支持延迟加载
public virtual Order Order { get; set; }
}
使用延迟加载代理查询数据
启用代理后,查询数据时不需要显式使用Include方法加载关联数据,当访问导航属性时,EF Core会自动触发查询加载关联数据,示例代码如下:
class Program
{
static void Main(string[] args)
{
using (var db = new AppDbContext())
{
// 查询订单,不显式加载关联的订单项
var order = db.Orders.FirstOrDefault(o => o.Id == 1);
if (order != null)
{
// 访问Items属性时,代理会自动从数据库加载该订单的所有订单项
foreach (var item in order.Items)
{
Console.WriteLine($"产品名称:{item.ProductName},数量:{item.Quantity}");
}
}
}
}
}
延迟加载代理的注意事项
- 延迟加载会导致额外的数据库查询,如果在循环中频繁访问导航属性,可能产生N+1查询问题,影响性能,这种情况下建议使用显式加载或者预先加载。
- 延迟加载代理创建的实体是代理类的实例,不是原始实体类的实例,如果需要判断实体类型,需要注意这一点。
- 如果实体的导航属性不是virtual的,即使启用了延迟加载代理,也无法触发延迟加载逻辑。
- 在禁用变更跟踪的场景下,延迟加载代理可能无法正常工作,因为代理需要变更跟踪来触发数据加载逻辑。