[英]At what point do I need to off-load the work of a query to the DB?
我有一个Web应用程序,并且正在使用实体框架连接到数据库。
例如,要选择特定部门的所有Employee
记录,我可以很容易地写出:
....Employees.Where(o => o.Department == "HR").ToList();
工作正常。 但这是最佳选择吗?
应该将此Where
子句合并到存储过程或视图中吗? 还是我的实体框架代码执行将其转换为SQL的工作?
过去,当人们将记录拉入内存, 然后在.net中而不是在数据库级别进行过滤时,我们的团队就遇到了性能问题。 我正尝试避免再次发生这种情况,因此想清楚我必须避免的事情。
如果Employees
是由Entity Framework提供的,则Where()
将转换为SQL并发送到数据库。 只是具体化了对象,才采用了之前应用的过滤器并将它们转换为SQL。 在那之后的任何事情都只是对象的普通LINQ。
导致实现发生的方法包括.ToList()
和.ToArray()
(还有更多,但是这两个可能是最常见的)。
如果要查看SQL Server上发生的情况,则应打开SQL事件探查器,并查看正在发送的查询。
过去,当人们将记录拉入内存,然后在.net中而不是在数据库级别进行过滤时,我们的团队就遇到了性能问题。
就像Colin答案的附录一样,并针对上面的引用,避免这种情况的方法是先确保使用IQueryable<T>
完全构建数据库查询,然后再使用诸如.ToList()
类的调用枚举结果。或.ToArray()
。
例如,请考虑以下内容:
IEnumerable<Employee> employees = context.Employees;
// other code, before executing the following
var hrEmployees = employees.Where(o => o.Department == "HR").ToList();
.ToList()
将枚举结果,首先从上下文中获取所有雇员, 然后在客户端上执行过滤。 如果您有很多员工要与之抗衡,那么这将无法很好地实现,而且扩展规模肯定也不会很好。
与此相比:
IQueryable<Employee> employees = context.Employees;
// other code, before executing the following
var hrEmployees = employees.Where(o => o.Department == "HR").ToList();
IQueryable<T>
从IEnumerable<T>
派生。 它们之间的区别是IQueryable<T>
具有内置的查询提供程序,而您构造的查询表示为表达式树。 这意味着只有在枚举查询结果的.ToList()
如.ToList()
,才会对其进行评估。
在上面的第二个示例中,查询提供程序将执行SQL以仅提取属于HR部门的那些雇员,从而对数据库本身执行过滤。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.