2011-11-17 14 views
5

Pracuję nad dużą aplikacją, która używa filtrowania Dynamic LINQ Library.Filtrowanie podzapytań za pomocą Dynamic LINQ

Wszystkie klasy w moim dostępu do danych warstwy wywodzą się od wspólnego DALAncestor przodka, który, między innymi, określa metodę GetData: public abstract Lista GetData (Filtr)

Implementacja tej metody Klient będzie wyglądać następująco (uproszczony):

public override List<Entities.Customer> GetData(Filter filter) { 
    var customers = from c in db.Customers 
        select new Entites.Customer { 
        ID = c.ID, 
        FullName = c.Name, 
        Country = c.Country 
        }; 

    return = filter.Apply(customers).ToList(); 
} 

„Zastosuj” jest metodą, która zajmuje zbiór warunków i stosuje je wszystkie za pomocą dynamicznej LINQ libary.

GetData Metoda nazywa się tak:

private void DemoCallGetDataMethod() { 
    var filter = new Filter(); 
    filter.AddCondition("Country", "Austria"); 

    var list = myCustomerDAL.GetData(filter); 
    // do something 
} 

SQL Server pobiera wybierz statment:

SELECT [t0].ID, [t0].Name, [t0].Country 
    FROM Customer [t0] 
WHERE [t0].Country = @p0 

(@ p0 jest parametr z wartością ustawioną na "Austria").

Wszystko działa świetnie, jeśli chcę filtrować wartości tylko na "najwyższym" (głównym) poziomie. Ponieważ jednak buduję filtr na danych wejściowych użytkownika w formularzu filtra, zdarzają się przypadki, w których użytkownicy chcą filtrować według wartości na poziomie szczegółowości (tj. Kolumny, które mają być filtrowane, są znane dopiero po kliknięciu przez użytkownika "Wyszukaj").

Nie mogę znaleźć rozwiązania: "Zdobądź wszystkich klientów z Austrii, którzy kupili Pepsi".

Próbowałem kilku rzeczy, żaden z nich nie działa. Podstawowym założeniem jest:
1. Add support for CONTAINS do DynamicLibrary
2. zmiana kodu do

public override List<Entities.Customer> GetData(Filter filter) { 
    var customers = from c in db.Customers 
        select new Entites.Customer { 
        ID = c.ID, 
        FullName = c.Name, 
        Country = c.Country, 
        Items = c.Order.SelectMany(o => o.Item).Select(i => i.ItemId).ToList() 
        }; 

    return = filter.Apply(customers).ToList(); 
} 

private void DemoCallGetDataMethod() { 
    var filter = new Filter(); 
    filter.AddCondition("Country","=", "Austria"); 
    filter.AddCondition("Items","Contains", "11"); // 11 = Id for Pepsi 

    var list = myCustomerDAL.GetData(filter); 

    // do something 
} 

exepction wrzucony jest:

System.InvalidOperationException: Żadna metoda rodzajowa 'zawiera' na type "System.Linq.Enumerable" jest kompatybilny z argumentami i argumentami dostarczonego typu. Nie należy podawać argumentów typu, jeśli metoda nie jest generyczna.

Czy ktoś ma pojęcie, co robię źle? Czy po prostu idę w złym kierunku i powinienem spróbować innego podejścia? Który? :)

edycja: zmienił mój przykład

+0

Niestety IAM nie wiem, co jest po wyrób wspomniałeś dostarczyła również odpowiedź do tego samego problemu jesteś w celu uniknięcia tego wyjątku. A ponieważ chcesz podążać tą trasą, naprawdę nie rozumiem, o co ci chodzi :)? – user182630

+0

filter.AddCondition ("Items", "Contains", "Pepsi"); - Działa to tylko dla String i String, a nie dla listy i string – Tsabo

+0

@ user182630 Chcę móc filtrować według wartości z podselekcji w ogóle, nie tylko dla konkretnego przypadku. Podejście z tego artykułu działa tylko wtedy, gdy ciężko kodujesz filtry, co nie jest rzeczą, którą mogę zrobić. –

Odpowiedz

2

@ user182630 Chcę być w stanie filtrować według wartości z obsługę żądań w ogóle, nie tylko dla konkretnego przypadku. Podejście z tego artykułu działa tylko wtedy, gdy zakodowałeś filtry, co nie jest rzeczą, którą mogę zrobić. - Marko Juvančič 9 minut temu

Prosze przeczytać tego artykułu http://csharpindepth.com/articles/chapter5/closures.aspx

2

używam PredicateBuilder dynamicznych zapytań w mojej aplikacji.

Predicate Builder

W twoim przypadku mogę sobie wyobrazić to będzie coś w stylu:

string MyCountry = "Austria"; 
string MyProductId = 11 

var Predicate = PredicateBuilder.True<db.Customers>(); 
Predicate = Predicate.And(p=>p.Country ==MyCountry && p.Order.SelectMany(o=>o.Item).Where(i=>i.id == 11).Count() >0); 

var list = Customers.Where(Predicate).Select(s=>s).ToList(); 
+0

To podejście kończy się niepowodzeniem w przypadku "kolumn do filtrowania przez są znane tylko po kliknięciu przez użytkownika" Szukaj "wymogu. –

+0

Dobrze, jeśli wszystkie kolumny są znane z góry, to nie jest problem. – Tsabo

+0

Nie są. Metoda "Zastosuj" filtr nie wie nic o kolumnach. –