【问题标题】:At what point do I need to off-load the work of a query to the DB?在什么时候我需要将查询工作卸载到数据库?
【发布时间】:2015-09-06 20:30:31
【问题描述】:

我有一个网络应用程序,我正在使用实体框架连接到一个数据库。

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

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

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

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

过去,当人们将记录拉入内存并然后在 .net 中而不是在数据库级别进行过滤时,我们的团队曾遇到过性能问题。我正在努力避免这种情况再次发生,所以我想清楚我必须避免什么。

【问题讨论】:

    标签: c# database asp.net-mvc-4 entity-framework-6


    【解决方案1】:

    如果Employees 由Entity Framework 提供,那么Where() 将被翻译成SQL 并发送到数据库。只有在您具体化对象时,它才会采用您之前应用的过滤器并将它们转换为 SQL。在那之后的任何东西都只是简单的 LINQ to objects。

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

    如果您想查看 SQL Server 上发生了什么,您应该打开 SQL Profiler 并查看正在发送的查询。

    【讨论】:

      【解决方案2】:

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

      作为 Colin 答案的附录,并针对上面的引用,避免这种情况的方法是确保您的数据库查询首先使用 IQueryable<T> 完全构建,然后使用诸如 @987654322 之类的调用枚举结果@,或.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&lt;T&gt; 派生自 IEnumerable&lt;T&gt;。它们之间的区别在于IQueryable&lt;T&gt; 内置了一个查询提供程序,并且您构造的查询表示为一个表达式树。这意味着在枚举查询结果的调用(例如.ToList())之前不会对其进行评估。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-04
        • 1970-01-01
        • 2010-09-21
        • 2018-02-25
        • 1970-01-01
        • 2012-09-16
        相关资源
        最近更新 更多