当前位置: 首页 > 知识库问答 >
问题:

是否应在web应用程序中禁用实体框架延迟加载?

卜盛
2023-03-14

我听说应该在web应用程序中禁用EF的延迟加载功能。(ASP.NET)。首先,这里和这里。

现在我真的很困惑,因为我一直认为应该始终启用延迟加载,因为它可以防止从数据库中获取不必要的数据。所以,现在我的问题是:从性能角度来看,在网络应用中禁用懒惰加载是否是一个更好的主意。如果是,你能解释一下原因吗?

共有3个答案

钱展
2023-03-14

我有一个遗留项目。当我在sql概要文件中检查有多少请求进入数据库时,我真的很惊讶。首页大概是180(!)!主页只有两个列表,每个列表中有20-30个项目。所以,您应该非常了解n1请求。您应该仔细检查代码,并对其进行检查。对我来说,延迟加载会带来很多问题。使用该功能时,您永远不知道有多少请求进入数据库

宋勇
2023-03-14

web应用程序中,您有许多来自不同用户的并发请求,每个请求的处理速度都非常快(至少应该如此),因此您希望在每个请求期间减少DB调用的数量,因为每个DB请求都是通过网络进行的。通过延迟加载,每次使用关系属性时,它都会再次调用DB,将此相关数据加载到实体集合中。因此,在一个http请求过程中,您可以通过这种方式向DB发出大量额外的请求,从性能角度来看,这确实会损害您的应用程序。在正常情况下,当您最初从数据库中获取数据时,您已经知道您需要哪些相关数据,因此您可以使用相关实体的快速加载,将一个请求中需要的所有内容加载到数据库中,以处理特定的http请求。

聂和宜
2023-03-14

禁用延迟加载将防止Select N 1性能问题以及递归序列化问题,但它会用另一个工件(空引用)替换这些问题。

在使用web应用程序时,我不会禁用延迟加载,而是确保我的控制器/API不会返回实体,而是返回ViewModels或DTO。当您采用使用POCO类为视图提供所需的数据量和结构时,请使用.Select()或Automapper的项目

采用ViewModel提供了许多优势:

  • 避免延迟加载调用或意外的#空引用。
  • 仅发送视图/消费者所需的数据,仅此而已。(线路上的数据更少,调试视图的黑客信息更少。)
  • 为数据库服务器构建高效的、可索引的查询。
  • 为不会触发EF的计算列提供位置。
  • 有助于减少返回途中的安全问题(意外的实体修改)。(视图模型不能简单地由懒惰的开发人员重新附加并提交到数据库)

因此,对我来说,web应用程序的问题不在于是否延迟加载,而在于避免将实体传递给客户端。我看到太多太多的“例子”,他们在那里传递实体。我不认为这是一种健康的模式。

通过使用视图模型,您可以将要检索的数据限制为视图所需要的数据。我创建了一个产品视图模型,它概述了我关心的字段,不管数据来自哪里。如果我想要像产品这样的东西,它是名称,它是类别名称:

public class ProductViewModel
{
    public int ProductId { get; set; }
    public string ProductName { get; set; }
    public string CategoryName { get; set; }
}

然后加载它:

var viewModel = context.Products
    .Where(x => x.ProductId == productId) 
    .Select(x => new ProductViewModel
    {
        ProductId = x.ProductId,
        ProductName = x.Name,
        CategoryName = x.Category.Name
    }).Single();

完成。不需要延迟加载或急切加载。这将生成一个查询,返回一条记录,其中只包含我们需要的3列。(而不是整个产品记录及其产品类别)

随着需求变得越来越复杂,我们可以引入视图模型层次结构,但我们可以根据视图的实际需要继续缩小相关数据。在某些情况下,这可能意味着选择匿名类型,然后将这些结果转换为视图模型,在视图模型中我们需要使用EF无法转换为SQL的函数等。该方法是依赖加载实体的一种强大而快速的替代方法,但在开始时需要注意了解最终消费者(视图/API)需要从数据中获得什么。

 类似资料:
  • 我从这个网站上读到了关于懒惰加载的内容。启用或禁用LazyLoding “如果我们请求已启用LazyLoading的学生列表,数据提供程序将从数据库中获取所有学生,但每个StudentAddress属性在显式访问该属性之前不会加载。” 此语句表示,当我将设置为true时,将不会加载相关数据。然而 如果我设置延迟加载启用=true,上面的代码返回所有特技与他们的老师和地址。我在这里错过了什么?有人能

  • 我在亲子关系中有几个实体:家庭(父母)和更新(孩子)。我想阅读没有相应更新的家庭列表。只有17个家庭,但大约有60,000个更新,所以我真的不想要更新。 我使用EntiesToDTO从Family实体生成DTO,并创建一个汇编器来将Family实体转换为FamilyDTO。汇编器的ToDTO方法如下所示: 当我运行汇编程序时,我发现每个生成的FamilyDTO都填充了Updates\u ID列表,

  • 考虑以下(非常简化的)实体: 在我的映射器中,我可以设置用户罚款,但是一旦执行以下代码(在数据库中保留任何更改之前)

  • 问题内容: 我倾向于将Hibernate与Spring框架结合使用,它具有声明式事务划分功能(例如@Transactional)。 众所周知,hibernate试图尽可能做到 非侵入性 和 透明性 ,但是事实证明,在使用关系时这 更具挑战性 。 我看到了许多具有不同透明度的设计方案。 使关系不延迟加载(例如, 这违反了整个延迟加载的想法。 使用初始化初始化集合 这意味着与DAO的耦合较高 尽管我们

  • 当将实体模型转换为DTO时,我对Entity Framework Core(v2.0.1)有一个问题。基本上,通过该短语的任何其他版本,当我不想加载时,它是延迟加载的。这是一个简单的。NET Core Console应用程序(带有Microsoft. EntityFrameworkCore. SqlServer(2.0.1)包)。 现在,当执行方法来检索数据时,它正在执行以下SQL 如您所见,它没

  • 我正在使用启用延迟加载的实体框架5。我有以下代码: 但这有意义吗?我想确保公共属性订阅从不为null。由于虚拟实体框架覆盖了getter和setter以提供延迟加载功能。 我需要这个字段还是我可以只使用一个自动属性,如果没有订阅,我得到一个空列表?