Как реализовать динамическое предложение "where" в LINQ?

Я хочу иметь динамическое условие where.

В следующем примере:

var opportunites =  from opp in oppDC.Opportunities
                    join org in oppDC.Organizations 
                        on opp.OrganizationID equals org.OrgnizationID
                    where opp.Title.StartsWith(title)
                    select new
                    {
                        opp.OpportunityID,
                        opp.Title,
                        opp.PostedBy,
                        opp.Address1,
                        opp.CreatedDate,
                        org.OrganizationName
                    };

Несколько раз у меня Title, а иногда я этого не делаю. А также я хочу добавить дату в выражении where динамически.

Например, как этот SQL:

string whereClause;
string SQL = whereClause == string.Empty ? 
     "Select * from someTable" : "Select * from someTable" + whereclause

Ответ 1

Вы можете переписать его следующим образом:

 var opportunites =  from opp in oppDC.Opportunities
                            join org in oppDC.Organizations on opp.OrganizationID equals org.OrgnizationID
                            select new
                            {
                                opp.OpportunityID,
                                opp.Title,
                                opp.PostedBy,
                                opp.Address1,
                                opp.CreatedDate,
                                org.OrganizationName
                            };

if(condition)
{
   opportunites  = opportunites.Where(opp => opp.Title.StartsWith(title));
}

РЕДАКТИРОВАТЬ: Чтобы ответить на ваш вопрос в комментариях, да, вы можете сохранить добавление к исходному Queryable. Помните, что это все лениво выполнено, поэтому на этом этапе все это делает это, создавая IQueryable, чтобы вы могли связывать их вместе по мере необходимости:

if(!String.IsNullOrEmpty(title))
{
   opportunites  = opportunites.Where(.....);
}

if(!String.IsNullOrEmpty(name))
{
   opportunites  = opportunites.Where(.....);
}

Ответ 2

Вы можете динамически добавлять предложение where к вашему выражению IQueryable следующим образом:

var finalQuery = opportunities.Where( x => x.Title == title );

и для даты аналогично.

Однако вам придется подождать, чтобы создать анонимный тип, пока после того, как вы закончите динамически добавлять свои предложения where , если, ваш анонимный тип не содержит полей, которые вы хотите запросить в своем где предложение.

Итак, у вас может быть что-то похожее на это:

var opportunities =  from opp in oppDC.Opportunities
                    join org in oppDC.Organizations on 
                    opp.OrganizationID equals org.OrgnizationID
                    select opp                            

if(!String.IsNullOrEmpty(title))
{
   opportunities = opportunities.Where(opp => opp.Title == title);
}

//do the same thing for the date

opportunities = from opp in opportunities
                select new
                        {
                            opp.OpportunityID,
                            opp.Title,
                            opp.PostedBy,
                            opp.Address1,
                            opp.CreatedDate,
                            org.OrganizationName
                        };

Ответ 3

Предложение WHERE может быть сделано как

//...
where string.IsNullOrEmpty(title) ? true : opp.Title.StartsWith(title)
//...

Динамическое возвращение записей, которые я не думаю, возможно в LINQ, так как он должен иметь возможность создавать последовательный анонимный тип (в фоновом режиме)

Ответ 4

Поскольку запросы являются составными, вы можете просто построить запрос пошагово.

var query = table.Selec(row => row.Foo);

if (someCondition)
{
    query = query.Where(item => anotherCondition(item));
}

Ответ 6

Если вы знаете заранее все возможное, когда запросы, подобные приведенному в примере SQL, вы можете написать запрос, подобный этому

from item in Items
where param == null ? true : ni.Prop == param
select item;

если вы не знаете все возможное, где предложения заранее, вы можете добавить, где dymically, например, вот так:

query = query.Where(item => item.ID != param);

Ответ 7

Я искал создание предложения dynamic where в LINQ и натолкнулся на очень красивое решение в Интернете, которое использует ExpressionBuilder в С#.

Я размещаю его здесь, так как ни одно из вышеупомянутых решений не использует этот подход. Это помогло мне. Надеюсь, это тоже поможет http://www.codeproject.com/Tips/582450/Build-Where-Clause-Dynamically-in-Linq

Ответ 8

Используйте это:

bool DontUseTitles = true; // (Or set to false...    
var opportunites =  from opp in oppDC.Opportunities
                    join org in oppDC.Organizations 
                        on opp.OrganizationID equals org.OrgnizationID
                    where (DontUseTitles | opp.Title.StartsWith(title))
                    select new
                    {
                        opp.OpportunityID,
                        opp.Title,
                        opp.PostedBy,
                        opp.Address1,
                        opp.CreatedDate,
                        org.OrganizationName
                    };

Почему это работает? Если DontUseTitles истинно, он выбирает все, потому что "(DontUseTitles | opp.Title.StartsWith(название))" оценивается как true. В противном случае он использует второе условие и просто возвращает подмножество.

Почему каждый всегда делает вещи более сложными, чем они должны быть?: -)