【发布时间】:2017-02-23 00:37:17
【问题描述】:
在我当前的应用程序中,我正在生成一个相当长的表格来显示给用户。我一直看到它存在一些严重的性能问题,我已经追踪到使用 @Html.DisplayFor,但我不完全确定原因。
编辑:我已将代码示例替换为更简洁和可重现的设置。
为了隔离问题,我使用 Visual Studio 中的所有默认设置创建了一个新的 asp.net core 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
}
这会在 13 毫秒内呈现。很明显,DisplayFor 正在为渲染增加大量时间……在我的 PC 上,每次调用将近 0.4 毫秒。虽然这在孤立的情况下还不错,但对于列表或其他事情来说,它是一个非常糟糕的选择。
DisplayFor 真的那么慢吗?还是我用错了?
【问题讨论】:
-
DisplayFor使用反射来访问对象中的每个属性,如果它是导航属性,这可能会触发 EF 延迟加载。这可能是正在发生的事情。 -
您不应在视图中使用持久性模型的另一个原因,请改用视图模型。虽然我们不知道 OP 使用什么,但 EFCore 还没有实现延迟加载,只有 EF6
-
我为此使用 EFCore。我很快将其转换为视图模型,并使用
members.Select(s => new MembersListViewModel {Id = s.Id}).ToList();选择了数据,但它似乎存在相同的性能问题。 -
实际上,跟进,使用视图模型大大提高了测试的性能,而不是使用显示,只需要5ms,但DisplayFor测试仍然需要400ms。所以感谢您的提示,但不幸的是,这并不是导致头痛的原因。
-
感谢您对 CodeCaster 的评论,我已经更新了该帖子,并至少需要重现它。我现在使用的代码基于默认模板(无身份验证),并且仅添加了一个控制器操作、视图和模型,并显示了所有代码。
标签: c# razor asp.net-core asp.net-core-mvc displayfor