Запрашиваете дочерние таблицы с динамическим linq для sql? - PullRequest
0 голосов
/ 28 октября 2011

У меня довольно сложный запрос, который мне нужно написать. Я надеюсь сделать это с помощью Linq to Sql, если это возможно. База данных примерно такая:

Клиенты (первый, последний, ID, пол)
Заказы (дата, количество, вес, наименование товара, цена)
Адрес (город, штат, почтовый индекс)

Запрос будет позволять пользователю выполнять поиск по любому из этих полей, а в случае числовых полей искать <, = или> по своему усмотрению.

Примерно так может быть пример запроса, который мне нужно реализовать:

Запрос 1: Выберите клиентов, чье имя = 'Джон' и у которых есть хотя бы один заказ с (Вес> 40 ИЛИ Количество> 10 ИЛИ Цена> 5) и почтовый индекс = 12345.

Запрос 2: Выберите клиентов, у которых имя = «Джон» и имеют хотя бы один заказ с весом <20 и ItemName = «виджет» и количеством = 10) и почтовым индексом = 12345. </p>

Я могу получить основную часть поиска клиентов, но я застрял при поиске в таблице заказов, где пользователь может указать <> = в виде ИЛИ.

</p>

<pre><code>query = Context.Customers.AsQueryable();
if (searchingFirstName) query = query.Where(cust => cust.First == firstName);
if (searchingLastName) query = query.Where(cust => cust.Last == lastName);
if (searchingZip) query = query.Where(cust => cust.Address.Zip == zip);

// using dynamic Linq
if (searchingGender) query = query.Where("Gender == @0", gender);

// how do I search the Orders?  The dynamic linq functions appear
// to only work on the top level table

1 Ответ

1 голос
/ 29 октября 2011

Вы можете использовать PredicateBuilder из LinqKit .Он добавляет некоторые новые методы расширения для предикатов лямбда-выражений:

var predicate = PredicateBuilder.True<Customer>();

if (searchingFirstName)
{
    predicate = predicate.And(cust => cust.First == firstName);
}

if (searchingOrders)
{
    // Some code to unify the .And() and .Or() cases
    Expression<Func<Order, bool>> subpredicate;
    Func<Expression<Func<Order, bool>>, Expression<Func<Order, bool>>, Expression<Func<Order, bool>>> joiner;
    if (orderMethodAny)
    {
        subpredicate = PredicateBuilder.True<Order>();
        joiner = PredicateBuilder.And;
    }
    else
    {
        subpredicate = PredicateBuilder.False<Order>();
        joiner = PredicateBuilder.Or;
    }

    if (searchingOrderDate)
    {
        // ...
    }

    if (searchingOrderWeight)
    {
        switch (orderOp)
        {
            case Op.Less:
                subpredicate = joiner(subpredicate, ord => ord.Weight < orderWeight);
                break;
            case Op.LessEqual:
                subpredicate = joiner(subpredicate, ord => ord.Weight <= orderWeight);
                break;
            case Op.Equal:
                subpredicate = joiner(subpredicate, ord => ord.Weight == orderWeight);
                break;
            case Op.GreaterEqual:
                subpredicate = joiner(subpredicate, ord => ord.Weight >= orderWeight);
                break;
            case Op.Greater:
                subpredicate = joiner(subpredicate, ord => ord.Weight > orderWeight);
                break;
            case Op.NotEqual:
                subpredicate = joiner(subpredicate, ord => ord.Weight != orderWeight);
                break;
        }
    }

    if (searchingOrderQuantity)
    {
       // ... 
    }

    if (searchingOrderItemName)
    {
        // ...
    }

    if (searchingOrderPrice)
    {
        // ...
    }

    predicate = predicate.And(cust => cust.Orders.Any(subpredicate));
}

if (searchingZipCode)
{
    predicate = predicate.And(cust => cust.ZipCode == zipCode);
}

var query = Context.Customers.Where(predicate);

Вам может потребоваться вызвать .Expand() для предикатов перед передачей их в качестве аргументов или .AsExpandable() для запрашиваемого, если вы используете EntityFramework.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...