我们应该在网络应用中禁用延迟加载Entity Framework吗? [英] Should we disable lazy loading of Entity Framework in web apps?

查看:84
本文介绍了我们应该在网络应用中禁用延迟加载Entity Framework吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我听说您应该在Web应用程序中禁用EF的延迟加载功能。 (ASP.NET)。 此处此处,供初学者使用。

I've heard that you should disable the lazy loading feature of EF in web applications. (ASP.NET). Here and here, for starters.

现在我真的很困惑,因为我一直认为应该始终启用延迟加载,因为它可以防止不必要的数据获取数据库。因此,现在我的问题是:就性能而言,禁用Web应用程序中的延迟加载通常是否是一个更好的主意。如果是,您能解释为什么吗?

Now I'm really confused here because I always thought that lazy loading should always be enabled because it prevents unnecessary data fetching the database. So, now my question is: Is it generally a better idea to disable lazy loading in web apps in terms of performance. If yes, could you explain why?

推荐答案

禁用延迟加载将防止Select N + 1性能问题以及递归序列化保释金-outs,但是它将替换为另一个工件,即空引用。

Disabling lazy loading will prevent Select N+1 performance problems as well as recursive serialization bail-outs, however it replaces those with another artifact, null references.

在使用Web应用程序时,我不会禁用延迟加载,而是确保我的控制器/ API不会返回,而是返回实体他们返回ViewModels或DTO。当您采用POCO类提供视图时,仅提供数据量及其所需的结构,并使用 .Select()或Automapper的 ProjectTo< ; TViewModel>()来通过延迟执行来填充它们,您无需担心延迟加载,并为应用程序引入了更好的整体性能和资源使用率。从技术上讲,使用这种方法可以禁用延迟加载,因此,它并不是禁用它的论据,而是禁用延迟加载的唯一行为不会使您的Web应用程序变得更好。

When working with web applications I do not disable lazy loading, but rather I ensure that my controllers/APIs do not return entities, but rather they return ViewModels or DTOs. When you adopt using POCO classes to feed your views just the amount of data, and the structure they need, and use .Select() or Automapper's ProjectTo<TViewModel>() to populate them via deferred execution, you avoid the need to worry about lazy load, and introduce better overall performance and resource usage for your application. Technically, using this approach, lazy loading can be disabled, so it's not really an argument for or against disabling it but rather that the mere act of disabling lazy loading won't make your web application "better".

采用ViewModels具有许多优点:

Adopting ViewModels offers a number of advantages:


  • 避免延迟加载调用或意外的#null引用。 / li>
  • 仅发送视图/消费者所需的数据,仅发送其他数据。 (通过有线方式传输的数据较少,并且对于具有调试视图的黑客来说,信息较少。)

  • 对数据库服务器建立有效的,可索引的查询。

  • 为不会导致EF跳闸的计算列提供一个位置。

  • 帮助减少回跳时的安全性问题(意外的实体修改)。 (一个懒惰的开发人员不能简单地将视图模型重新附加并提交给数据库)

  • Avoids lazy load calls or unexpected #null references.
  • Sends only the data needed by the view/consumer, and nothing more. (Less data over the wire, and less information for hackers with debugging views.)
  • Builds efficient, index-able queries to the database server.
  • Provides a place for computed columns that won't trip up EF.
  • Helps reduce security issues (unexpected entity modifications) on the trip back. (A view model cannot simply be re-attached and committed to DB by a lazy developer)

所以对我来说,网络问题应用程序不是要延迟加载还是不延迟加载,只是避免将实体传递给客户端。我看到了太多的示例,它们在其中传递实体。我认为这不是一个健康的模式。

So for me, the issue with web applications isn't to lazy load or not, it's simply to avoid passing entities to the client. I see far, far too many "examples" out there where they pass entities around. I don't consider it a healthy pattern.

例如,使用视图模型,第一个问题是我的视图实际上需要什么数据?因此,给定一个产品和一个产品类别,如果我想发送一个产品实体,但是我还需要一个产品类别名称,例如,如果我们的产品类别包含一个产品集合,并且每个产品都有一个类别。当我们将产品传递给序列化程序时,它将到达该循环引用,并且将退出紧急状态(留下引用或集合#null),否则将引发异常。但是,通过选择N + 1,我们将遍历Product属性,点击ProductCategory参考,然后选择从ProductCategory中选择,其中ProductCategoryID = 3。然后,当我们遍历该产品类别时,我们找到了另一个参考,这是另一个SELECT ....如此反复。

As an example, using a view model the first question is "What data does my view actually need?" So given a product and a product category, if I want to send a product entity, but I also need the product category name for instance we hit a nasty problem if our product category contains a collection of products, and each of those products has a category. When we pass our product to the serializer it's going to hit that cyclic reference and it's either going to bail out (leaving a reference or collection #null) or it is going to throw an exception. But working through the Select N+1 we would iterate over the Product properties, hit the ProductCategory reference, then "SELECT FROM ProductCategory WHERE ProductCategoryID = 3". Then as we iterate over that product category, we hit another reference, and that is another SELECT.... and so-forth down the chain.

使用视图通过模型,您可以将要检索的数据限制为仅视图所需的数据。我创建了一个产品视图模型,该模型概述了我关心的领域,而不管数据来自何处。如果我想要类似产品的名称,那么它的名称就是类别名称:

By using a view model you limit the data you want to retrieve to just what the view needs. I create a Product View-model which outlines the fields I care about, irregardless of where the data comes from. If I want something like a product, it's name, and it's category name:

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列的单个记录。 (而不是整个产品记录,而是产品类别)

Done. No lazy loads or eager loads required. This produces a single query that returns a single record with just the 3 columns we need. (Rather than the entire Product record, and it's Product Category)

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

As requirements get more complex we can introduce a view model hierarchy, but we can continue to flatten down the related data based on what the view actually needs. In some cases it might mean selecting into an anonymous type then translating those results into view models where we need to use functions etc. that EF cannot translate down to SQL. The approach is a powerful and fast alternative to relying on loading entities, but requires attention at the start to understand what the end consumer (view/API) will need from the data.

这篇关于我们应该在网络应用中禁用延迟加载Entity Framework吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆