是否应在Web应用程序中禁用Entity Framework延迟加载? [英] Should Entity Framework lazy loading be disabled in web apps?

查看:50
本文介绍了是否应在Web应用程序中禁用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 from 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性能问题以及递归序列化纾困,但是它将替换为另一个工件(空引用).

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 返回实体,而是它们返回ViewModel或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引用.
  • 仅发送视图/消费者所需的数据,仅此而已.(通过网络传输的数据较少,而对于具有调试视图的黑客来说,信息较少.)
  • 构建对数据库服务器的高效,可索引的查询.
  • 为不会导致EF跳闸的计算列提供一个位置.
  • 帮助减少回程中的安全性问题(意外的实体修改).(一个懒惰的开发人员不能简单地将视图模型重新附加并提交给数据库)

因此,对我来说,Web应用程序的问题不是要延迟加载还是不要延迟加载,只是避免将实体传递给客户端.我看到了太多的示例",它们在其中传递实体.我认为这不是一种健康的方式.

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.

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

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