2014-11-05 3 views
3

У меня есть метод в моем приложении, который должен читать, фильтровать и обслуживать данные на основе набора критериев. Я пытаюсь использовать LINQ для достижения этой цели:Как динамически конструировать/изменять часть оператора LINQ

var pipelineData = from data in new XPQuery<AccountView3.PipelineData>(uow) 
     where data.Stage.ToLower().Contains("won") 
     && data.RevenueStartDate.Value.Year == DateTime.Today.Year 
     && data.WeekOfTheYear >= priorWeekCutoff 
     && (!string.IsNullOrEmpty(data.PlatformTcv) && data.PlatformTcv != "#N/A") 
     select data; 

Само по себе это работает просто отлично. Проблема заключается в том, что в зависимости от критериев поиска, которые передаются, вместо данных. ПлатформаTvc может быть data.WorkspaceTvc или data.CyberTvc и т. Д. У меня нет возможности заранее знать, какой из возможных Необходимо оценить 5 вариантов.

Мой вопрос: есть ли способ построить оператор LINQ таким образом, чтобы часть инструкции была условно выполнена. Поэтому, если пользователь передает «Платформу» в качестве критериев поиска, оператор LINQ будет читать ... string.IsNullOrEmpty(data.PlatformTcv), но если критерии «Cyber», то этот оператор LINQ должен читать ... string.IsNullOrEmpty(data.CyberTcv) Есть ли способ сделать это ?

ответ

9

Несомненно. Воспользуйтесь моделью отложенного исполнения LINQs и вставьте сменный переменный в запрос. Например:

Func<DataObject, string> accessor = data => data.PlatformTcv; 

var pipelineData = from data in new XPQuery<AccountView3.PipelineData>(uow) 
        where data.Stage.ToLower().Contains("won") 
         && data.RevenueStartDate.Value.Year == DateTime.Today.Year 
         && data.WeekOfTheYear >= priorWeekCutoff 
         && (!string.IsNullOrEmpty(accessor(data)) 
         && accessor(data) != "#N/A") 
        select data; 

var basedOnPlatform = pipelineData.ToArray(); 

accessor = data => data.CyberTV; 

var basedOnCyber = pipelineData.ToArray(); 

(. При этом предполагается, тип элемента запроса DataObject Конечно, вы бы заменить, что с фактическим именем любого типа вы используете).

Просто помните, что это сделает LINQ более трудным для понимания и всегда помнит о продолжительности вашего запроса. То есть если они не «материализованы» как некоторая другая коллекция (например, вызывают ToArray()), тогда изменения в базовом запросе будут отображаться при следующем ее выполнении.

+0

Going попробовать это сейчас ... –

+0

Это было гений! Спасибо! –

2

Вы можете создать IQueryable для той части, которая одинакова для всех запросов:

var pipelineData = from data in new XPQuery<AccountView3.PipelineData>(uow) 
    where data.Stage.ToLower().Contains("won"); 
    // etc 

Затем применить конкретный фильтр:

if (somecondition) 
{ 
    pipelineData = pipelineData.Where(x => x.SomeField == "somevalue"); 
} 
// etc 
+0

Осторожно. OP _might_ хочет повторно использовать исходный запрос (не совсем понятный мне из сообщения), поэтому вам не захочется назначать новую отфильтрованную версию обратно исходной переменной. Стоит отметить, что, по крайней мере, для исходного примера, это решение, скорее всего, будет более читаемым, более простым в обслуживании, чем тот, который я предложил. Он не обобщает на другие элементы запроса LINQ, но IMHO это очень хороший выбор, если вы просто делаете фильтрацию. –

+0

Я полностью согласен. –

Смежные вопросы