Linq where子句混淆

Linq where clause confusion

大家好!

我已经为我的自动化测试编写了一个查询,但执行起来花费的时间太长,而且我不确定如何有效地优化它,因为我是 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 子句中调用其他存储库(假设存储库实际访问数据库)这实际上意味着您正在为每个查询项目访问数据库。假设 OrderRepositoryX.GetOrderByStatus(OrderStatusType.Dispatched, 4000) 和第一个 Where 将产生 1000 个项目,只有第二个 Where 子句将导致对数据库的 1000 个查询(并且您在后续 Wheres)。所有这一切只得到一件物品(即 FirstOrDefault)。

通常的方法是避免在循环中调用数据库(Where 在这里基本上是这样做的)并重写这样的代码,因此只对数据库执行单个 SQL 查询,只返回需要的和在数据库端执行所有过滤。

请试试这个 避免过多的 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;
                });