LINQ to SQL Где условие Необязательный критерий

Я работаю с запросом LINQ to SQL и столкнулся с проблемой, когда у меня есть 4 необязательных поля для фильтрации результата данных. По выбору, я имею в виду, имеет ли выбор ввести значение или нет. В частности, несколько текстовых полей, которые могут иметь значение или иметь пустую строку и несколько выпадающих списков, которые могли иметь значение, выбранное или, возможно, не...

Например:

    using (TagsModelDataContext db = new TagsModelDataContext())
     {
        var query = from tags in db.TagsHeaders
                    where tags.CST.Equals(this.SelectedCust.CustCode.ToUpper()) 
                    && Utility.GetDate(DateTime.Parse(this.txtOrderDateFrom.Text)) <= tags.ORDDTE
                    && Utility.GetDate(DateTime.Parse(this.txtOrderDateTo.Text)) >= tags.ORDDTE
                    select tags;
        this.Results = query.ToADOTable(rec => new object[] { query });
    }

Теперь мне нужно добавить следующие поля/фильтры, но только если они предоставлены пользователем.

  • Номер продукта - поступает из другой таблицы, которая может быть присоединена к устройствам TagsHeaders.
  • PO Number - поле внутри таблицы TagsHeaders.
  • Номер заказа - аналогично PO #, только другой столбец.
  • Состояние продукта. Если пользователь выбрал это из раскрывающегося списка, необходимо применить выбранное значение здесь.

Запрос, который у меня уже есть, отлично работает, но для завершения функции нужно иметь возможность добавлять эти 4 других элемента в предложение where, просто не знаю, как это сделать.

Ответ 1

Вы можете запрограммировать свой исходный запрос:

var query = from tags in db.TagsHeaders
                where tags.CST.Equals(this.SelectedCust.CustCode.ToUpper()) 
                && Utility.GetDate(DateTime.Parse(this.txtOrderDateFrom.Text)) <= tags.ORDDTE
                && Utility.GetDate(DateTime.Parse(this.txtOrderDateTo.Text)) >= tags.ORDDTE
                select tags;

И затем, основываясь на условии, добавьте дополнительные ограничения.

if(condition)
    query = query.Where(i => i.PONumber == "ABC"); 

Я не уверен, как закодировать это с синтаксисом запроса, но id работает с лямбдой. Также работает с синтаксисом запроса для исходного запроса и лямбдой для вторичного фильтра.

Вы также можете включить метод расширения (ниже), который я закодировал некоторое время назад, чтобы включить условие, в котором содержатся утверждения. (Не работает с синтаксисом запроса):

        var query = db.TagsHeaders
            .Where(tags => tags.CST.Equals(this.SelectedCust.CustCode.ToUpper()))
            .Where(tags => Utility.GetDate(DateTime.Parse(this.txtOrderDateFrom.Text)) <= tags.ORDDTE)
            .Where(tags => Utility.GetDate(DateTime.Parse(this.txtOrderDateTo.Text)) >= tags.ORDDTE)
            .WhereIf(condition1, tags => tags.PONumber == "ABC")
            .WhereIf(condition2, tags => tags.XYZ > 123);

Метод расширения:

public static IQueryable<TSource> WhereIf<TSource>(
    this IQueryable<TSource> source, bool condition,
    Expression<Func<TSource, bool>> predicate)
{
    if (condition)
        return source.Where(predicate);
    else
        return source;
}

Вот такой же метод расширения для IEnumerables:

public static IEnumerable<TSource> WhereIf<TSource>(
    this IEnumerable<TSource> source, bool condition,
    Func<TSource, bool> predicate)
{
    if (condition)
        return source.Where(predicate);
    else
        return source;
}

Ответ 2

Просто нужно использовать условную проверку для существования параметра. Например:

where (string.IsNullOrEmpty(ProductNumber) || ProductNumber == tags.productNumber)

Таким образом, если номер продукта не введен, выражение будет возвращать true во всех случаях, но если оно будет введено, оно будет возвращать true только при сопоставлении.