Динамическое предложение where в Linq to Entities

Я использую linq to entity (EF). У меня есть конструктор, который принимает 4 строковых параметра. В зависимости от того, какой параметр не равен нулю, мне нужно создать запрос linq. Я могу использовать операторы if else, но у меня также есть другой конструктор с 10 параметрами, в этом случае нужно будет проверить множество комбинаций.

Пример:

Constructor(p1,p2,p3,p4)
{
  var prod= from p in ctxt.products.expand("items\details")
            where p.x==p1 && p.xx==p2 && p.xxx==p3 && p.xxxx==p4
            select p;
}

В приведенном выше предложении where должны выполняться проверки условий только в том случае, если параметр не равен нулю. то есть, если p2 равен нулю, то предложение where должно выглядеть как

where p.x==p1 && p.xxx==p3 && p.xxxx==p4

если p2 и p3 равны нулю, то

where p.x==p1 && p.xxxx==p4

Кто-нибудь может сказать мне, как с этим справиться. если возможно, вы можете дать образец кода для этого


person Deepak    schedule 03.02.2012    source источник
comment
Возможный дубликат stackoverflow.com/questions/697345/   -  person Michael Freidgeim    schedule 04.10.2012


Ответы (3)


На помощь приходит отложенное выполнение Linq. Запрос Linq не выполняется, если от него не запрашиваются данные.

var prod = from p in ctxt.products.expand("items\details")
        select p;

if (p1 != null)
{
    prod = prod.Where(p => p.x == p1);
}

if (p2 != null)
{
    prod = prod.Where(p => p.xx == p2);
}

// Execute the query

var prodResult = prod.ToList();
person amit_g    schedule 03.02.2012
comment
если мы это сделаем, мы будем загружать большой объем данных в prod, а затем берем их подмножество. Можем ли мы получить подмножество напрямую. - person Deepak; 03.02.2012
comment
Запрос НЕ выполняется до тех пор, пока не будет построено предложение where. В приведенном выше коде запрос строится до самой последней строки, и именно там он выполняется. Вы можете исправить это, запустив профилировщик SQL. - person amit_g; 03.02.2012
comment
Да вы правы. Я могу использовать ваш код, и он отлично работает. - person Deepak; 03.02.2012
comment
мы можем здесь использовать async? - person HamedH; 20.06.2017
comment
Здесь p1 и p2 складываются в условии AND. Есть ли способ принудительно выполнить соединение OR? - person Afshar Mohebi; 13.05.2019

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

 YourType(string p1, string p2, string p3, string p4)
 {
      var prod = ctxt.Products.Expand("items\details");

      if (!p1.IsNullOrWhiteSpace())
          prod = prod.Where(p => p.x == p1);
      if (!p2.IsNullOrWhiteSpace())
          prod = prod.Where(p => p.xx == p2);

      // ....

      // use "prod"
 }

Результирующий SQL должен быть таким же, как если бы вы поместили их все в один оператор.

person Reed Copsey    schedule 03.02.2012
comment
если мы это сделаем, мы будем загружать большой объем данных в prod, а затем берем их подмножество. Можем ли мы получить подмножество напрямую, иначе мы загружаем ненужные данные - person Deepak; 03.02.2012
comment
@Deepak Нет, не поймешь. Плюс IQueryable в том, что он не загружает данные - LINQ использует отложенное выполнение, а с EF переводит окончательный запрос в один оператор SQL. Это будет тот же результат. - person Reed Copsey; 03.02.2012
comment
@Deepak Подробнее см .: stackoverflow.com/questions / 1578778 / using-iqueryable-with-linq / - person Reed Copsey; 03.02.2012
comment
Здесь p1 и p2 складываются в условии AND. Есть ли способ принудительно выполнить соединение OR? - person Afshar Mohebi; 13.05.2019

Вы всегда можете построить запрос по частям и воспользоваться преимуществами отложенного выполнения запроса:

public Constructor(int? p1, int? p2, int? p3, int? p4)
{
    var prod = ctxt.products.expand("items\details");

    if(p1 != null)
        prod = prod.Where(p.x == p1);

    if(p2 != null)
        prod = prod.Where(p.xx == p2);

    if(p3 != null)
        prod = prod.Where(p.xxx == p3);

    if(p4 != null)
        prod = prod.Where(p.xxxx == p4);
}
person Justin Niessner    schedule 03.02.2012
comment
если мы это сделаем, мы будем загружать большой объем данных в prod, а затем берем их подмножество. Можем ли мы получить подмножество напрямую, иначе мы загружаем ненужные данные - person Deepak; 03.02.2012
comment
@Deepak - Вы вообще не будете загружать данные. LINQ не выполняет запрос, пока вы не используете данные. К моменту выполнения запроса у вас уже будут соответствующие предложения where для загрузки только необходимых данных. - person Justin Niessner; 03.02.2012
comment
Здесь p1 и p2 складываются в условии AND. Есть ли способ принудительно выполнить соединение OR? - person Afshar Mohebi; 13.05.2019