Conditional operator in Linq Expression causes NHibernate exception
Asked Answered
M

1

6

I'm trying to implement search functionality in an ASP.NET MVC 2 application. I create an expression based on criteria entered by the user:

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
                                                            ); 

which then gets passed to a method in the repository

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

The problem is when I run this I get the following exception

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

According to this the problem is the use of the conditional operator in the expression.

So I suppose I have to create the Expression some other way but I'm not sure how to do that. I'm pretty new to Linq so any help would be gratefully accepted!

Magpie answered 19/3, 2012 at 17:9 Comment(0)
S
10

What about dynamically create your query? Like this:

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);

I don't know if this works but I think this could be more efficient.

Such answered 19/3, 2012 at 19:26 Comment(3)
That works! Thanks very much. I'd been trying to avoid writing something like that because I wanted to avoid multiple calls to the database so I thought I needed to construct a single expression containing all the parameters. Using your solution only executes a single SQL statement. Is that a feature of NHibernate? It builds a SQL statement from multiple LINQ expressions to minimise calls to the database? I think I need to learn more about both NHibernate and LINQ!Magpie
@Magpie This is a feature of LINQ. Your query won't be evaluated till you call a ToList or SingleOrDefault (or similar) method at the end of your IQueryable chain, so you can dynamically add any filters to your query. After an explicit call the query processor (like NHibernate) will transform the whole query chain into a SQL expression.Such
@Magpie I have used such expressions when I used Entity framework and there, it just worked fine. Why it doesnt work in nHibernate ?China

© 2022 - 2024 — McMap. All rights reserved.