IQueryable 的性能表现

5

我需要在客户数据库上编写一个动态查询,以获取客户的几个字段。

以下是代码:

[Route("api/getBasicCustList/{argType}/{argValue}")]
        [HttpGet]
        [Authorize]

        public dynamic getCustomerDataUsername(String argType, String argValue)
        {
            IQueryable<CustomerDTO> query =
               (from recordset in db.Customers
                     select new CustomerDTO
                               {
                                   companyId = recordset.Company.Id,
                                   contactNum = recordset.ContactNum,
                                   username = recordset.UserName,
                                   emailAddress = recordset.Email,
                                   fullName = recordset.FullName,
                                   accountNumber = recordset.RCustId
                               }
                );

            switch (argType)
            {
                case "username" :
                    query = query.Where(c => c.username.StartsWith(argValue));
                    break;
                case "contactnum":
                    long mobNum = Int64.Parse(argValue);
                    query = query.Where(c => c.contactNum == mobNum);
                    break;
                case "fullname":
                    query = query.Where(c => c.fullName.Contains(argValue));
                    break;
            }

            return new { data = query.ToList() };
        }

这很好用,符合我的需求。
我的问题是,当我编写查询的第一部分以获取所有客户记录,并稍后动态应用 where 条件时,结果是在内存中获取还是完整的查询一次性在数据库中生成和执行?
由于目前只有 500 条记录,我无法找到任何性能滞后,但当我将其投入生产时,我将处理至少 200,000 到 300,000 条记录。

5
直到你在方法结尾处使用了“ToList”,查询才会被执行。 - Kinetic
哦,太好了!能否请您或其他人提供一个来自 MSDN 或任何在线文章的链接来确认这一点。谢谢。 - Lakshman Pilaka
2
请看查询执行 - Georg Patscheider
1
@LakshmanPilaka,也许您可以在您的评论中添加一些文字,并将其作为答案添加。 - Bassam Alugili
1
你可以随时使用一些分析器或 Database.Log 来查看查询的执行情况。然后你会发现查询将在 ToList 调用之后执行。更多信息请参见:https://msdn.microsoft.com/zh-cn/data/dn469464.aspx - matiii
这实际上归结为数据库性能。你使用的数据库和索引是什么。如果建议你使用没有全文索引的SQL Server,我会避免使用LIKE查询(当使用.Where(c => c.fullName.Contains(argValue))时)。然而,这完全取决于数据量有多大。 - Torbjörn Hansson
2个回答

4

好的,答案是

只有当你到达方法末尾的“ToList”时,查询才会执行。

从@GeorgPatscheider分享的MSDN 链接中提到:

查询表达式何时执行可能会有所不同。当遍历查询变量而不是创建查询变量时,始终会执行LINQ查询。这称为延迟执行。

延迟执行允许组合多个查询或扩展查询。当查询被扩展时,它将被修改以包括新操作,并且最终执行将反映更改。

还写道,如果查询具有任何AverageCountFirstMax,它将执行立即执行

谢谢。


2
查询性能仍受Sql的影响 - 例如,请记住在案例谓词中为所有筛选列创建索引。为了保持一致,您可能希望标准化使用Linq的查询语法或lambda语法...您已经将两者结合在一起了。 - StuartLC

0
在大型表查询性能方面,提高性能的最大因素是在服务器(数据库)端进行过滤。在Entity Framework 6.x及更早版本中,如果EF无法将整个查询转换为SQL,则查询将无法编译。在EF Core中,不再如此。尽可能多的查询将被转换为SQL。其余部分将在客户端上评估。
您的所有三个过滤lambda表达式都可以转换为SQL。但是,如果您编写了一个无法转换的谓词,则在EF Core上,性能会受到影响。尽管查询的评估仍然推迟到调用ToList()之前,但Customers表中的所有记录都将被发送到客户端进行过滤。您的日志将包含警告,但很容易忽略。
关于这一点的良好参考是Jon Smith的文章“Entity Framework Core: Client vs. Server evaluation”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接