首页 > 解决方案 > 如何使用 Entity Framework 减少对数据库的调用

问题描述

我正在使用 10+(取决于用例)对数据库的调用,只是为了在我的视图中填充下拉列表。

就像这里显示的代码一样:

ViewBag.FK_Grupe_Predmeta_ID = new SelectList(db.Get_Grupe_Predmeta(userLanguageID).ToList(), "ID", "Naziv");
ViewBag.FK_Klasifikacione_Oznake_ID = new SelectList(db.Get_Klasifikacione_Oznake(userLanguageID).ToList(), "ID", "Naziv");
ViewBag.FK_Stranke_ID = new SelectList(db.Strankes.Where(s => s.Povjerljiv == true), "ID", "Naziv");
ViewBag.FK_Prioriteti_ID = new SelectList(db.Get_Prioriteti(userLanguageID).ToList(), "ID", "Naziv");
ViewBag.odjeljenja = new SelectList(db.Get_Odjeljenja(userLanguageID).OrderBy(x => x.Naziv).ToList(), "ID", "Naziv");
ViewBag.VrstePostupka = new SelectList(db.Vrsta_Postupkas.ToList(), "PK_Vrsta_Postupka_ID", "Naziv_Vrste_Postupka");

我称之为存储过程和表。但是当我同时对多个用户进行测试时,加载时间会很长,有时甚至是几分钟。

找不到任何方法来减少通话并同时填充ViewBag。有谁知道在这种情况下最好的方法是什么?

谢谢

标签: asp.net-mvcentity-framework

解决方案


一个建议不是将整个实体集传递给 SelectList 构造函数,而是只发送所需字段的投影。除非绝对必要,否则我可能会避免调用存储过程,并让 EF 与表交互以构建最佳查询。

var strankes = db.Stranks
    .Where(x => x.Povjerljiv)
    .Select(x => new { x.ID, x.Naziv });
ViewBag.FK_Stranke_ID = new SelectList(stranks, "ID", "Naziv");

对于常见的查找,您可以将 ID 和 Name(Naziv) 投影到视图模型,然后考虑将它们缓存到会话以避免每次页面加载时重新加载它们。您的 SelectList 是从缓存的视图模型中构建的,而不是再次访问数据库。

确保您的 DbContext 生命周期范围设置不超过每个请求。随着时间的推移,存活时间更长并跟踪更多实体的 DbContext 在检索和更新实体时变得慢得多。它跟踪的越多,当您请求某些内容时,它将筛选的缓存实体越多,然后去数据库读取更多实体,然后将这些结果实体与它的本地缓存缝合。(用于填充任何相关实体等)为了在快速加载集合时获得最佳性能,请考虑在查找实体之间具有最少导航属性的有界上下文(仅映射 FK 列)并通过本地范围的有界 DbContext 读取。

其他需要注意的性能缺陷是实体可能被序列化并发送到视图的任何地方。具有查找导航属性等的实体被序列化程序“触及”,最终可能会触发延迟加载,以一次加载每个相关实体。我的建议总是将实体投影到 ViewModels 以发送到视图以避免这样的陷阱。由于查询延迟负载陷阱可以生成,它们看起来很像正在触发查找查询的情况。SQL Profiler 对于发现在页面加载时意外生成大量查询的情况非常有帮助。


推荐阅读