0

Assuming the following code that applies filtering logic to a passed on collection.

private IQueryable<Customer> ApplyCustomerFilter(CustomerFilter filter, IQueryable<Customer> customers)
{
    ...
    if (filter.HasProductInBackOrder == true)
    {
        customers = customers.Where(c => c.Orders.Any(o => o.Products.Any(p => p.Status == ProductStatus.BackOrder)))
    }
    ....

    return customers;
}

Results in this SQL statement:

SELECT [Extent1].[CustomerId] AS [CustomerId], 
       [Extent1].[Status] AS [Status] 
FROM [Customers] AS [Extent1] 
WHERE
(
    EXISTS 
    ( 
        SELECT 1 AS [C1]
        FROM
        (
            SELECT [Extent3].[OrderId] AS [OrderId]
            FROM   [Orders] AS [Extent3]
            WHERE  [Extent1].[CustomerId] = [Extent3].[CustomerId]
        ) AS [Project1]
        WHERE  EXISTS
        ( 
            SELECT 1 AS [C1]
            FROM [Products] AS [Extent4] 
            WHERE  ([Project1].[OrderId] = [Extent4].[OrderId]) 
            AND    ([Extent4].[Status] = @p__linq__6)
        )
    )
)

However, I would like to optimize this by forcing to use INNER JOINS so that the result will be similar to this:

SELECT [Extent1].[CustomerId] AS [CustomerId], 
       [Extent1].[Status] AS [Status] 
FROM [Customers] AS [Extent1] 
INNER JOIN [Orders] AS [Extent2] ON [Extent1].[CustomerId] = [Extent2].[CustomerId]
INNER JOIN [Products] AS [Extent3] ON [Extent2].[OrderId] = [Extent3].[OrderId]
WHERE [Extent3].[Status] = @p__linq__6

I've tried multiple approaches, but I was unable to accomplish the desired result. Any suggestions on how to force the correct joins and avoiding subselects?

Niels R.
  • 7,260
  • 5
  • 32
  • 44
  • 1
    `INNER JOIN` equivalent in LINQ is `SelectMany`. You can try to rewrite your condition with two `SelectMany` and a `GroupBy`, but you have to consider this https://stackoverflow.com/a/2177379/1812077 – Leff Oct 13 '20 at 15:14
  • 1
    Invert your query, by Firstly select the orders with this rule (Products.Where(p => p.Status == ProductStatus.BackOrder), then join it with your customers table and then you apply the Any filter, give it a try. – Bruno Oct 13 '20 at 15:40

0 Answers0