【问题标题】:Linq where clause confusionLinq where 子句混淆
【发布时间】:2021-12-27 12:29:27
【问题描述】:

大家好!

我为自动化测试编写了一个查询,但执行时间太长,而且我不确定如何有效优化它,因为我是 Linq where 子句的新手。

有人可以帮我解决这个问题吗?

var order = OrderRepositoryX.GetOrderByStatus(OrderStatusType.Dispatched, 4000)
            .Where(x => x.siteId == 1 || x.siteId == 10 || x.siteId == 8 || x.siteId == 16 || x.siteId == 26 || x.siteId == 27)
            .Where(x =>
            {
                var totalPrice = OrderRepository.GetOrderById(shared_parameters.testConfiguration, x.orderId).TotalPrice;
                if (totalPrice < 500)
                    return false;
                return true;
            })
            .Where(x =>
            {
                var cnt = ReturnOrderRepositoryX.CheckReturnOrderExists(x.orderId);
                if (cnt > 0)
                    return false;
                return true;
            })
            .Where(x =>
            {
                var cnt = OrderRepositoryX.CheckActiveOrderJobDetailsByOrderId(x.orderId);
                if (cnt > 0)
                    return false;
                return true;
            })
            .FirstOrDefault();

【问题讨论】:

  • 尝试在调试模式下将每个 where 作为自己的语句执行,以找出哪个子句正在减慢您的应用程序
  • 是 EF 还是只是 LINQ to Entities?
  • 您在 where 子句中执行了其他存储库代码...这意味着您的 linq 查询未转换为 SQL。它可能会提取内存中的所有数据,然后对其应用条件。这就是您性能缓慢的原因之一。
  • @SvyatoslavDanyliv - 它是英孚
  • @draz - 好的 - 我会检查调试这个

标签: c# linq


【解决方案1】:

这里最大的代码异味是您在 Where 子句中调用其他存储库(假设存储库实际访问数据库)这实际上意味着您正在访问每个查询项目的数据库。让我们假设OrderRepositoryX.GetOrderByStatus(OrderStatusType.Dispatched, 4000) 和第一个Where 将产生1000 个项目,只有第二个Whereclause 将导致对数据库的1000 个查询(并且您在随后的Wheres 中有更多对存储库的调用)。所有这一切都只得到一件物品(即FirstOrDefault)。

通常的方法是避免在循环中调用数据库(Where 基本上在这里所做的)并重写此类代码,以便仅对数据库执行单个 SQL 查询,仅返回所需内容并在数据库端执行所有过滤.

【讨论】:

    【解决方案2】:

    请试试这个 避免过多的 where 子句。它得到一个结果,然后对整个集合应用另一个检查。

    var order = OrderRepositoryX.GetOrderByStatus(OrderStatusType.Dispatched, 4000)
                        .FirstOrDefault(x => x.siteId == 1 || x.siteId == 10 || x.siteId == 8 || x.siteId == 16 ||
                                    x.siteId == 26 || x.siteId == 27) &&
                    (x =>
                    {
                        var totalPrice = OrderRepository.GetOrderById(shared_parameters.testConfiguration, x.orderId)
                            .TotalPrice;
                        return totalPrice >= 500;
                    })
                    && (x =>
                    {
                        var cnt = ReturnOrderRepositoryX.CheckReturnOrderExists(x.orderId);
                        return cnt <= 0;
                    })
                    && (x =>
                    {
                        var cnt = OrderRepositoryX.CheckActiveOrderJobDetailsByOrderId(x.orderId);
                        return cnt <= 0;
                    });
    

    【讨论】:

    • 谢谢 Smitha - 我会尝试这种方法
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 2010-10-10
    • 2021-02-02
    相关资源
    最近更新 更多