2012-06-17 3 views
1

Я пытаюсь выяснить, как использовать PredicateBuilder, чтобы определить, существует ли какой-либо набор записей в пределах выражения. Поэтому, учитывая OrderId и список ProductIds в качестве спецификации, я хочу знать, содержат ли записи OrderDetail Order все элементы спецификации. Не только один или некоторые из них, но все они.Создание автономного булева выражения с PredicateBuilder

Так что я мог бы сделать:

var inner = PredicateBuilder.False<OrderDetail>(); 

foreach (int spec in specs) 
{ 
    temp = spec;    
    inner = inner.Or(d => d.ProductId == temp); 
} 

var outer = PredicateBuilder.True<OrderDetail>(); 

outer = outer.And(d => d.OrderId == orderId); 
outer = outer.And(inner); 

Но затем, после того, как я получаю результат, я бы а) устранить дубликаты (потому что в моем случае несколько Детали_Заказов может иметь тот же ProductId), а затем б) сравните счетчик результатов с подсчетом spec. Все это выполнимо вне выражения, но есть ли элегантный способ оценить все это в выражении, чтобы результат был логическим?

То есть, я хотел бы, чтобы выражение было самодостаточным, чтобы его можно было передавать как есть, и те, которые я ему даю, не должны знать, как делать «пост-обработку», чтобы фигурировать если это правда.

+0

В чем заключается основной провайдер linq? – AakashM

ответ

0

Для примера, который вы указали, я считаю, что вы можете сделать это намного проще, посмотрев на него по-другому.

Вместо того чтобы работать с вашим заказомДетали, начните со своих спецификаций и убедитесь, что они все в коллекции OrderDetails. Это одна строка кода будет соответствовать вашим требованиям, убедившись, что конкретный идентификатор заказа содержит все функции, и это вовсе не сложно:

bool containsAllSpecs = specs.All 
    (s => orderDetails.Any (p => p.OrderId == orderId && p.ProductId == s)); 

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

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

static class MyExtensions 
{ 
    public static bool ContainsAllSpecs(this IEnumerable<OrderDetail> orderDetails, 
     int orderId, 
     IEnumerable<int> specs) 
    { 
     return specs 
     .All (s => orderDetails.Any (p => p.OrderId == orderId && p.ProductId == s)); 
    } 
} 

И тогда вы могли бы назвать его из кода, как:

bool containsAllSpecs = orderDetails.ContainsAllSpecs(orderId, specs); 
Смежные вопросы