繁体   English   中英

在什么时候我需要将查询工作卸载到数据库?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM