实体框架上的懒惰与急切加载性能

amh*_*hed 9 c# asp.net-mvc entity-framework code-first azure-sql-database

所以我的DbContext上有以下模型类:

贷款

每次我渲染一个LoanApplication对象列表时,我都会这样做:

var context = new MyContext();
var applications = context.LoanApplications.Where(d => d.PropertyThatIWantToFilter = localVariable);
Run Code Online (Sandbox Code Playgroud)

这将返回一个IQueryable,然后我在我的控制器方法调用上转换为这样的ViewModel:

var vm = applications.Select(d => new LoanApplicationViewModel(d));
Run Code Online (Sandbox Code Playgroud)

LoanApplicationViewModel构造函数内部,我接受实体对象并执行相应的映射.问题在于,由于Solicitors集合是一个导航属性,因此每次实例化新的视图模型时都会对数据库进行调用.每个应用程序的平均律师数量是两个,这意味着如果我呈现一个列出最后10个应用程序的表,那么该应用程序将大约18-20次访问数据库.

我认为必须有一个更好的方法来获得这个集合,所以我改变了我的原始查询以急切加载集合,如下所示:

var applications = context.LoanApplications.Include("Solicitors").Where...
Run Code Online (Sandbox Code Playgroud)

虽然这会将对数据库的调用次数减少到只有一次,但查询速度要慢得多,大约慢50%.

该数据库托管在SQL Azure中,我们已经实现了瞬态故障处理,但我想,以减少不降低响应时间的性能对数据库进行调用的数量.

这里的最佳做法是什么?

Sle*_*ith 14

"这里的最佳做法是什么?"

最好的做法是

  1. 设置!应用范围广!绩效目标
  2. 轮廓,基准和定位瓶颈
  3. 检查并微调瓶颈,为您提供最佳性能,赢得最少的工作.(根据我的经验,90%的时间不是tsql)

现在看起来似乎有点无关紧要,但从这个角度来看,哪种加载模式你在应用程序域中最佳化是正确的方法.

渴望/懒惰没有"最佳实践".这就是为什么两种选择都可用的原因.此外,如果tsql是你的瓶颈,并且渴望/懒惰之间的切换仍然没有达到你的性能目标,你将需要在SSMS中查看大量其他工具,例如查询分析器和查询计划分析器.


对于某些背景:

我正在谷歌搜索"急切加载慢"来到这里.这是我的结果:

var foo = _context.Foos
    //.Include("Answers")
    //.Include("Attachments")
    .FirstOrDefault(q => q.Id == key);
Run Code Online (Sandbox Code Playgroud)

渴望加载:106ms

延迟加载:11ms + 5ms + 5ms

懒人装载获胜,故事结束.


Mal*_*are 0

如果您可以以某种方式查询您的律师表并使用已获取的应用程序列表过滤查询,那么获取的实体将缓存在您的上下文中,我相信它将用于导航属性而不是访问数据库。

我不确定如何编写律师获取查询,但我在想这样的事情

int[] applicationIDs = applications.Select(x => x.ID).ToArray();
var solicitors = context.Solicitors.Where(x => x.Applications.Any(y => applicationIDs.Contains(y.ID))).ToArray(); // added toarray to cause execution cause im never sure when the LINQ actually runs
Run Code Online (Sandbox Code Playgroud)