Entity Framework Core 中的延迟加载与即时加载大揭秘!性能考量全知道,助你高效开发!

简介: 【8月更文挑战第31天】Entity Framework Core (EF Core) 是一款强大的对象关系映射(ORM)框架,支持延迟加载与即时加载两种方式。延迟加载即访问关联实体时再加载,适用于减少初始查询负载,但可能导致多次数据库查询;即时加载则在查询主实体时一并加载关联实体,减少数据库访问次数,但可能增加初始查询复杂度。选择加载方式需综合考虑查询复杂性、数据量及数据库连接管理等因素。

Entity Framework Core(EF Core)是一个强大的对象关系映射(ORM)框架,它提供了多种方式来加载相关实体。其中,延迟加载和即时加载是两种常见的加载方式,它们在性能方面有着不同的考量。

一、延迟加载

延迟加载是指在访问相关实体时才实际加载它们。在 EF Core 中,延迟加载通常通过使用虚拟属性来实现。当访问虚拟属性时,EF Core 会自动发出查询来加载相关实体。

例如,假设我们有两个实体类,CustomerOrder,一个客户可以有多个订单:

public class Customer
{
   
    public int Id {
    get; set; }
    public string Name {
    get; set; }
    public virtual ICollection<Order> Orders {
    get; set; }
}

public class Order
{
   
    public int Id {
    get; set; }
    public int CustomerId {
    get; set; }
    public string Description {
    get; set; }
}

在默认情况下,EF Core 会使用延迟加载来加载CustomerOrders集合。当我们访问一个客户的订单时,EF Core 会自动发出查询来加载订单:

using (var context = new MyDbContext())
{
   
    var customer = context.Customers.FirstOrDefault();
    if (customer!= null)
    {
   
        // 此时不会加载订单,只有在访问 Orders 属性时才会加载
        var orders = customer.Orders;
        foreach (var order in orders)
        {
   
            Console.WriteLine(order.Description);
        }
    }
}

延迟加载的优点是可以减少初始查询的负载,只在需要的时候加载相关实体。然而,它也有一些缺点。首先,延迟加载可能会导致多次查询数据库,这可能会影响性能,特别是在处理大量相关实体时。其次,如果在访问相关实体时数据库连接已经关闭,就会抛出异常。

二、即时加载

即时加载是指在查询主实体时同时加载相关实体。在 EF Core 中,可以使用Include方法来实现即时加载。

例如,我们可以在查询客户时同时加载他们的订单:

using (var context = new MyDbContext())
{
   
    var customer = context.Customers.Include(c => c.Orders).FirstOrDefault();
    if (customer!= null)
    {
   
        foreach (var order in customer.Orders)
        {
   
            Console.WriteLine(order.Description);
        }
    }
}

即时加载的优点是可以减少数据库查询的次数,提高性能。它还可以确保在数据库连接关闭之前加载所有相关实体。然而,即时加载可能会导致初始查询变得更加复杂和耗时,特别是当加载多个相关实体时。

三、性能考量

在选择延迟加载还是即时加载时,需要考虑以下性能因素:

  1. 查询复杂性:如果查询主实体已经很复杂,即时加载可能会使查询更加复杂,影响性能。在这种情况下,延迟加载可能是更好的选择。
  2. 数据量:如果相关实体的数据量很大,延迟加载可能会导致多次查询数据库,影响性能。在这种情况下,即时加载可能是更好的选择。
  3. 数据库连接管理:如果需要确保在访问相关实体时数据库连接仍然打开,即时加载是更好的选择。否则,延迟加载可能会导致异常。

四、示例代码

以下是一个完整的示例代码,展示了延迟加载和即时加载的使用:

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;

namespace EfCoreLazyLoadingVsEagerLoading
{
   
    public class Customer
    {
   
        public int Id {
    get; set; }
        public string Name {
    get; set; }
        public virtual ICollection<Order> Orders {
    get; set; }
    }

    public class Order
    {
   
        public int Id {
    get; set; }
        public int CustomerId {
    get; set; }
        public string Description {
    get; set; }
    }

    public class MyDbContext : DbContext
    {
   
        public DbSet<Customer> Customers {
    get; set; }
        public DbSet<Order> Orders {
    get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
   
            optionsBuilder.UseSqlServer("YourConnectionString");
        }
    }

    class Program
    {
   
        static void Main()
        {
   
            using (var context = new MyDbContext())
            {
   
                // 延迟加载示例
                var customer = context.Customers.FirstOrDefault();
                if (customer!= null)
                {
   
                    Console.WriteLine($"Customer: {customer.Name}");
                    // 此时不会加载订单,只有在访问 Orders 属性时才会加载
                    var orders = customer.Orders;
                    if (orders!= null && orders.Any())
                    {
   
                        Console.WriteLine("Orders:");
                        foreach (var order in orders)
                        {
   
                            Console.WriteLine($"  - {order.Description}");
                        }
                    }
                }

                Console.WriteLine();

                // 即时加载示例
                var customerWithOrders = context.Customers.Include(c => c.Orders).FirstOrDefault();
                if (customerWithOrders!= null)
                {
   
                    Console.WriteLine($"Customer: {customerWithOrders.Name}");
                    Console.WriteLine("Orders:");
                    foreach (var order in customerWithOrders.Orders)
                    {
   
                        Console.WriteLine($"  - {order.Description}"});
                    }
                }
            }

            Console.ReadLine();
        }
    }
}

在这个示例中,我们首先使用延迟加载来加载客户和他们的订单,然后使用即时加载来加载客户和他们的订单。通过比较两种加载方式的性能和行为,可以更好地理解在不同情况下应该选择哪种加载方式。

总之,在 Entity Framework Core 中,延迟加载和即时加载都有各自的优点和缺点。在选择加载方式时,需要考虑查询复杂性、数据量和数据库连接管理等性能因素,以选择最适合的加载方式。

相关文章
|
12月前
jetson错误(三):E: 有未能满足的依赖关系。请尝试不指明软件包的名字来运行“apt --fix-broken install”(也可以指定一个解决办法
在NVIDIA Jetson平台上遇到“未能满足的依赖关系”错误时,可以通过运行“sudo apt-get -f install”或“sudo apt-get --fix-broken install”命令来解决。
957 2
|
5月前
|
存储 人工智能 移动开发
uni-app+vue3接入deepseek-v3搭建跨端ai流式(小程序+app+h5)
基于Uniapp+Vue3+Markdown接入DeepSeek-V3聊天大模型,支持编译到H5+小程序+App端。实现流式输出、支持亮色/暗黑主题、代码高亮、会话本地存储等功能。
887 12
|
SQL 开发框架 关系型数据库
不会使用 EF Core 的 Code First 模式?来看看这篇文章,手把手地教你
不会使用 EF Core 的 Code First 模式?来看看这篇文章,手把手地教你
688 0
|
前端开发
HTML中的pre标签表示空格或换行
HTML中的pre标签表示空格或换行
431 0
|
12月前
|
设计模式 Java 测试技术
优雅代码,建议掌握这 11个编程原则!
高质量的代码不仅让人信服,还能提升开发效率。本文总结了多位高手的经验,提炼出11条编码基本原则:DRY(避免重复)、KISS(简洁至上)、重构(优化代码)、SOLID(设计原则)、文档编写、创建优于继承、YAGNI(避免过度设计)、委托原则、始终保持代码清洁、封装变化以及优先使用组合而非继承。遵循这些原则,你的代码将更加优雅和高效。
495 3
|
设计模式 缓存 Devops
微服务架构最强讲解,那叫一个通俗易懂!
微服务架构(Microservice Architecture)是一种架构概念,旨在通过将功能分解到各个离散的服务中以实现对解决方案的解耦。你可以将其看作是在架构层次而非获取服务的
29900 2
微服务架构最强讲解,那叫一个通俗易懂!
|
开发框架 Oracle 关系型数据库
ABP框架使用Oracle数据库,并实现从SQLServer中进行数据迁移的处理
ABP框架使用Oracle数据库,并实现从SQLServer中进行数据迁移的处理
|
关系型数据库 MySQL 数据库
使用阿里云的数据传输服务DTS(Data Transmission Service)进行MySQL 5.6到MySQL 8.0的迁移
【2月更文挑战第29天】使用阿里云的数据传输服务DTS(Data Transmission Service)进行MySQL 5.6到MySQL 8.0的迁移
494 2
|
存储 数据采集 前端开发
ClkLog 实践中的挑战:如何设计和实施有效的埋点指标
前端数据埋点要怎么做才能获取到有用的数据并对运营产生积极的作用,对于首次实施埋点及数据分析的工程师来说确实是个难点。网上很多文章讲的都是方法论和理论知识,真正实践的内容比较少,我们从一个案例来描述一下埋点要如何做。
ClkLog 实践中的挑战:如何设计和实施有效的埋点指标
|
SQL 程序员 数据库
总结查看 .NET EF 生成的 SQL 的 3 种方式,亲测可用
总结查看 .NET EF 生成的 SQL 的 3 种方式,亲测可用
326 0