2012-03-19 12 views
6

Próbuję zaimplementować funkcję wyszukiwania w aplikacji ASP.NET MVC 2. Tworzę wyraz na podstawie kryteriów wprowadzonych przez użytkownika:Operator warunkowy w wyrażeniu Linq powoduje wyjątek NHibernate

public ViewResult FindCustomer(string forename, string familyname, DateTime? dob) 
    { 
    Expression<Func<Customer, bool>> searchCriteria = p => (
                  forename.IsNullOrEmpty() ? true : p.Forename == forename 
                  && familyname.IsNullOrEmpty() ? true : p.FamilyNames.Any(n => n.Name == familyname) 
                  && dob.HasValue ? true : p.DOB == dob 
                  ); 

który następnie zostanie przekazany do metody w repozytorium

IQueryable<Customer> customers = CustomerRepository.FilterBy(searchCriteria); 

Problem jest, gdy uruchomię to pojawia się następujący wyjątek

System.InvalidCastException: Unable to cast object of type 'NHibernate.Hql.Ast.HqlCast' to type 'NHibernate.Hql.Ast.HqlBooleanExpression' 

Zgodnie z this problemem jest użycie operatora warunkowego w wyrażeniu.

Więc przypuszczam, że muszę stworzyć Wyrażenie w inny sposób, ale nie jestem pewien, jak to zrobić. Jestem całkiem nowy w Linq, więc każda pomoc zostanie przyjęta z wdzięcznością!

Odpowiedz

9

Co powiesz na dynamiczne utworzenie zapytania? W ten sposób:

var customers = CustomerRepository.AllEntities(); 

if (!forename.IsNullOrEmpty()) 
    customers = customers.Where(p => p.Forename == forename); 
if (!familyname.IsNullOrEmpty()) 
    customers = customers.Where(p => p.FamilyNames.Any(n => n.Name==familyname)); 
if (dob.HasValue) 
    customers = customers.Where(p => p.DOB == dob); 

Nie wiem, czy to działa, ale myślę, że to może być bardziej wydajne.

+0

To działa! Dziękuję bardzo. Próbowałem uniknąć pisania czegoś takiego, ponieważ chciałem uniknąć wielu wywołań do bazy danych, więc pomyślałem, że muszę skonstruować pojedyncze wyrażenie zawierające wszystkie parametry. Korzystanie z rozwiązania powoduje wykonanie tylko jednej instrukcji SQL. Czy to jest cecha NHibernate? Tworzy instrukcję SQL z wielu wyrażeń LINQ w celu zminimalizowania wywołań do bazy danych? Myślę, że muszę dowiedzieć się więcej o NHibernate i LINQ! – Babakoto

+1

@Babakoto Jest to funkcja LINQ. Twoje zapytanie nie zostanie ocenione, dopóki nie wywołasz metody 'ToList' lub' SingleOrDefault' (lub podobnej) na końcu łańcucha 'IQueryable', dzięki czemu można dynamicznie dodawać dowolne filtry do zapytania. Po jawnym wywołaniu procesor zapytania (jak NHibernate) przekształci cały łańcuch zapytania w wyrażenie SQL. –

+0

To świetnie. Jeszcze raz dziękuję za pomoc – Babakoto