Объединение результатов с пустым запросом LINQ - PullRequest
1 голос
/ 12 февраля 2012

В базе данных у меня есть некоторые товары и цены. Мне нужно искать пределы цены. Проблема в том, что может быть несколько ограничений. Например, 0 - 500 $ 1500 - 2000

Как объединить запросы LINQ

var products = from product in db.Products
where product.Price >= 0 and product.Price <= 500

var products = from product in db.Products
where product.Price >= 1500 and product.Price <= 2000

Мой вариант:

  IQueryable<Deal> allResults = null;
            for(var i = 0; i < price.Length - 1; i = i + 2)
             {
              decimal start,end;
              decimal.TryParse(price[i], out start);
              decimal.TryParse(price[i+1], out end);

              var tempResults = from product in query
                         where (product.DiscountPrice >= start && product.DiscountPrice <=                    end)
                       select product;
                    tempResults.Union(allResults);
                }

как создать пустой запрос на присоединение?

Ответы [ 2 ]

3 голосов
/ 12 февраля 2012

Один способ состоит в объединении условий:

var products = from product in db.Products
where (product.Price >= 0 and product.Price <= 500)||product.Price >= 1500 and product.Price <= 2000

Другой способ заключается в использовании Union или Concat:

var products = (from product in db.Products
                     where product.Price >= 0 and product.Price <= 500)
         .Union(from product in db.Products
                     where product.Price >= 1500 and product.Price <= 2000);

Адаптация кода может:

IQueryable<Deal> allResults = null;
for(var i = 0; i < price.Length - 1; i = i + 2)
{
    decimal start,end;
    decimal.TryParse(price[i], out start);
    decimal.TryParse(price[i+1], out end);

    var tempResults = from product in db.Products
                      where (product.DiscountPrice >= start && product.DiscountPrice <= end)
                      select product;
    if(allResults!=null)
       allResults=allResults.Union(tempResults);
    else
       allResults=tempResults;
}

Вам не нужен пустой запрос для объединения, вы можете просто добавить специальный случай, который проверяет, является ли это первый запрос.

Но мне не нравится этот кодмного, потому что это смешивает две проблемы: построение запросов и слияние запросов.Так что я бы разделил его на две части:

IEnumerable<Tuple<Decimal,Decimal>> ParsePrices(string[] rawPrices)
{
    for(var i = 0; i < price.Length - 1; i = i + 2)
    {
       decimal start=decimal.Parse(price[i]);
       decimal end  =decimal.Parse(price[i+1]);

       yield return Tuple.Create(start, end);
}

var prices=ParsePrices(rawPrices);
IEnumerable<IQueryable<Deal>> partialQueries=prices.Select( interval=>
       from product in db.Products
       where (product.DiscountPrice >= interval.Item1 && product.DiscountPrice <= interval.Item2)
       select product;);
var mergedQuery=partialQueries.Aggregate((q1,q2)=>q1.Union(q2));
2 голосов
/ 12 февраля 2012

Вы можете создать пустой запрос, используя Enumerable.Empty<T>().AsQueryable().

Проблема в вашем коде: Union не изменяет никакие последовательности, которые вы передаете ему в качестве параметров; скорее, он создает новую последовательность, которую он возвращает. Таким образом, вы должны присваивать результат вашей tempResults.Union(allResults) операции allResults.

Вот пример кода (не тестировался):

IQueryable<Deal> filteredResults = Enumerable.Empty<Deal>().AsQueryable();

for (int i = 0; i < price.Length - 1; i += 2)
{
    decimal start, end;
    decimal.TryParse(price[i], out start);
    decimal.TryParse(price[i+1], out end);

    var tempResults = from product in db.Products
                      where product.DiscountPrice >= start && product.DiscountPrice <= end
                      select product;

    filteredResults = filteredResults.Union(tempResults);
}
...