views:

50

answers:

4

I am working on a search web page for my site. The requirements state that users can enter text for any combination of 9+ fields and the search should do an 'AND' match when querying the database. I could fairly quickly write this as a stored procedure using 'ISNULL' but I'm trying to figure out how to accomplish the same thing in LINQ. I thought I could query the results of a query, but I'm getting the error

"Only arguments that can be evaluated on the client are supported for the String.Contains method"

Here's my example

var people = db.People

if(null != fname)
{
people= from e in people
   where e.FirstName.Contains(fname)
   select e;
}

if(null != lname)
{
people= from e in people
   where e.LastName.Contains(lname)
   select e;
}

return people;

Can I query the resultset of a previous query? Is there a better approach I'm just not thinking of?

Thanks in advance.

+3  A: 

How is your fname and lname defined?

You should look at PredicateBuilder here - especially if you also want OR at some time:

http://www.albahari.com/nutshell/predicatebuilder.aspx

lasseespeholt
I will look into PredicateBuilder, thank you.
Craig G.
+2  A: 

This should work and seems simpler:

people = from e in db.People
    where (lname == null || e.LastName.Contains(lname))
       && (fname == null || e.FirstName.Contains(fname))
    select e;

The code you provided doesn't have anything obvious wrong with it, as there is no reason you can't query the results of another query. It looks like fname or lname are being defined in some way that the SQL generator doesn't understand.

Gabe
+1, Good solution, and it works in Linq-to-Sql. Just FYI, I have had problems with that pattern using LLBLGen before.
kbrimington
That worked like a charm, thanks.
Craig G.
If this is passed to SQL in the same form as above it will run *badly*
gbn
@Craig: If this solved your question, please mark it as an answer.
kbrimington
gbn: How will this run more badly than any other query? There's no way to run a query like this without a table scan, and that's probably orders of magnitude slower than any other part of the query.
Gabe
Since this is being interpreted into SQL, Gabe is right that it doesn't matter. However, I generally go with the approach in the original submission because when dealing with Lists (where it's actually running on the .Net side), it will make a (probably negligible) difference. It also seems cleaner to me to build it up incrementally, especially when you end up having more than just a few conditions.
John Gibb
+4  A: 

This should do it:

var people = db.People;
if(!String.IsNullOrEmpty(fname))
    people = people.Where(p => p.FirstName.Contains(fname));
if(!String.IsNullOrEmpty(lname))
    people = people.Where(p => p.LastName.Contains(lname));
return people;
Dustin Laine
+3  A: 

I'll sometimes accomplish the same thing in fewer lines by calling the extension methods directly:

var people = from e in db.People select e;

if(null != fname)
{
   people = people.Where(e => e.FirstName.Contains(fname));
}

if(null != lname)
{
    people = people.Where(e => e.LastName.Contains(lname));
}

return people;
kbrimington