2016-10-13 113 views
5

在我当前的应用程序中,我生成了一个相当长的表格以显示给用户。我已经看到了一些严重的性能问题,我已经跟踪了@ Html.DisplayFor的使用情况,并且我不完全确定为什么。在ASP.NET Core MVC中缓慢的DisplayFor性能MVC

编辑:我用更简洁和可重现的设置替换了代码示例。

为了找出问题,我使用visual studio中的所有默认设置创建了一个新的asp.net核心MVC项目,但没有进行身份验证。我创建的视图模型作为这样:

public class TestingViewModel 
{ 
    public int Id { get; set; } 
    public string TextValue1 { get; set; } 
    public string TextValue2 { get; set; } 
} 

然后加入控制器,其填满了数据的数据视图模型传递给视图:

public IActionResult TestThings() 
    { 
     var list = new List<TestingViewModel>(); 
     for(var i = 0; i < 1000; i++) 
      list.Add(new TestingViewModel {Id = i, TextValue1 = "Test", TextValue2 = "Test2"}); 

     return View(list); 
    } 

的视图是最低限度的能够显示数据:

@model List<DisplayForTest.ViewModels.TestingViewModel> 

@foreach (var item in Model) 
{ 
    @Html.DisplayFor(m => item.Id) 
    @Html.DisplayFor(m => item.TextValue1) 
    @Html.DisplayFor(m => item.TextValue2) 
} 

运行此代码时,它需要超过一秒的时间才能运行!罪魁祸首是DisplayFor。如果我改变视图如下:

@model List<DisplayForTest.ViewModels.TestingViewModel> 

@foreach (var item in Model) 
{ 
    @item.Id 
    @item.TextValue1 
    @item.TextValue2 
} 

这在13ms呈现。很明显,DisplayFor在我的个人电脑上增加了大量的时间来渲染......每次通话时间将近0.4ms。虽然这不是孤立的,但它使它成为列表或其他事物的一个非常糟糕的选择。

DisplayFor真的就这么慢吗?或者我使用不正确?

+2

'DisplayFor'使用反射来访问对象中的每个属性,如果它是导航属性,则可能会触发EF延迟加载。这可能是发生了什么事情。 – Dai

+0

为什么不应该在视图中使用持久性模型的另一个原因是使用视图模型。虽然我们不知道OP使用什么,但EFCore没有延迟加载实现,只有EF6 – Tseng

+0

我正在使用EFCore。我很快将它转换为视图模型,并使用'members.Select(s =>新的MembersListViewModel {Id = s.Id})。ToList();'选择数据,但它似乎具有相同的性能问题。 – Doddler

回答

2

DisplayFor真的就这么慢吗?或者我使用不正确?

评估和执行lambda表达式需要一些开销。首先框架必须validate it,然后evaluate it我在这里推测一下,但看起来这可能是性能问题来自的地方;这两种方法都需要反思。

我玩过的所有其他显示方法(ValueForDisplayTextFor等)在您的示例中具有相同的性能效果。

我不能说MVC团队为什么将它用于默认脚手架,但它确实对我有意义。 DisplayFor可以处理最常见的两种用例(显示属性的值,并使用自定义模板显示属性的值),并且在大多数情况下执行得相当好。

在这种情况下,我没有看到只使用原始值(基本.ToString荷兰国际集团的话),或者根据你在找什么的Html.Encode/Html.Raw方法中使用它的问题。

+0

对于不需要像这样的自定义显示模板的类型,我们得出结论:'DisplayFor'过度杀伤了吗?我很清楚,如果我希望在页面上显示这么多记录,我不能依赖它。有10列,我渲染的每一行将使用'DisplayFor'服务器4-5ms,这是不可接受的。我确实尝试了'ValueFor',虽然速度稍快,但它仍然非常慢。我使用它的主要原因是脚手架自动启动它。如果这是预期的行为,我可以接受它作为答案。 – Doddler

+0

@Doddler对于'ValueFor'表现你是对的 - 我的答案有点不合时宜。我已经更新了我的答案,以更好地解决问题。 –

+2

感谢您的帮助!解决了它之后,我倾向于直接输出常规类型,并使用TagHelpers或HtmlHelpers来显示更复杂的类型。我希望为标签助手带来一些成本,但他们看起来非常有效。 – Doddler