2015-09-06 64 views
1

我有一个web应用程序,并且我正在使用实体框架连接到一个数据库。在什么时候需要将查询的工作卸载到数据库?

要选择所有Employee记录某一个部门的,例如,我可以很容易地写:

....Employees.Where(o => o.Department == "HR").ToList();

工作正常。但它是最优的?

这个Where子句应该被合并到存储过程或视图中吗?或者,我的实体框架代码是否可以完成将其转换为SQL的工作?

过去从我们团队中发现性能问题时,人们会将记录拉入内存,然后在.net而不是数据库级别执行筛选。我试图避免这种情况再次发生,所以想要清楚我必须避免的事情。

回答

1

如果Employees由实体框架提供,那么Where()将被翻译成SQL并发送到数据库。只有这样,您才能实现对象,而不必将之前应用的过滤器转换为SQL。在那之后的任何事情只是简单的LINQ到对象。

导致物化发生的方法包括诸如.ToList().ToArray()(还有更多,但这两个可能是最常见的)。

如果您想查看SQL Server上正在发生的事情,应该打开SQL事件探查器并查看正在发送的查询。

1

从过去人们将记录拉入内存然后在.net而不是在数据库级进行过滤的过去,我们在过去的团队中遇到过性能问题。

只是作为附录科林的回答,并针对上面的报价,以避免这种情况的办法是,以确保您的数据库查询与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())之后才会对其进行评估。

在上面的第二个示例中,查询提供程序将执行SQL以仅提取属于HR部门的员工,对数据库本身执行过滤。

相关问题