views:

474

answers:

5

I am wanting to create a Where statement within my Linq statement, but have hit a bit of a stumbling block.

I would like to split a string value, and then search using each array item in the Where clause.

In my normal Sql statement I would simply loop through the string array, and build up there Where clause then either pass this to a stored procedure, or just execute the sql string. But am not sure how to do this with Linq to Entity?

( From o In db.TableName Where o.Field LIKE Stringvalue Select o ).ToList()
+1  A: 

How about

(from o in db.Tablename
    where o.Field.Contains(Stringvalue)
    select o).ToList();
Lazarus
A: 
var fcs = from c in Contacts
          where c.FirstName.ToLower().StartsWith(e.value.ToLower())
          select c;

You can use any string functions like contains, startswith etc

ashish jaiman
Many people use the ToLower() trick, but you don't have to. StartsWith has an overload in which you can supply StringComparison.InvariantCultureIgnoreCase
Zyphrax
A: 

EDIT: Misinterpreted your question, how about:

string filters = "a,b,c,d";
var result = from filter in filters.Split(',')
             from record In db.TableName
             where record.Field.Contains(filter)
Zyphrax
This is an equality comparison, not a `LIKE` operation.
Adam Robinson
@Adam, you're right, misinterpreted the question :)
Zyphrax
This works when the text I am searching with is exact, but not for partial matches. But thanks for the code as it will come in handy down the line
Tim B James
+1  A: 

To do dynamic construction it's probably best to use an expression tree. Give this a shot:

IQueryable<EntityType> query = db.Tablename;
Expression<Func<EntityType, bool>> expression = null;

foreach (string item in yourString.Split(","))
{
    string localItem = item; // so that we don't close over the loop variable

    Expression<Func<EntityType, bool>> exp = x => x.FieldName.Contains(localItem);

    if (expression == null)
    {
        expression = exp;
    }
    else
    {
        expression = Expression.Lambda<Func<int, bool>>(
            Expression.OrElse(expression.Body,  
            Expression.Invoke(exp,expression.Parameters.Cast<Expression>())), 
            expression.Parameters);
    }
}

var results = query.Where(expression).ToList();
Adam Robinson
Thanks AdamThis works, although only returns a list which match the final item in the string array.So if the string value was "a,b,c,d" it would only return those matching "d".Is there a way to join the query within the for loop so that the final query.ToList() contains query.where(x => x.fieldname.contains("a")) and query.where(x => x.fieldname.contains("b")) .... ?
Tim B James
You could use Union to chain the queries together, like my answer
MarkJ
@Jim: Give this edit a shot. My original answer was wrong in that it a) was designed to be an `AND`, when you really want an `OR`, and b) it closed over the loop variable (d'oh!), which is why it only matched the last condition.
Adam Robinson
Hi Adam, sorry for the delay.The code produces an error of: "The LINQ expression node type 'Invoke' is not supported in LINQ to Entities."
Tim B James
A: 

Air code building on Adam's answer and using Union to chain the results together, emulating AND rather than OR.

EDIT I removed my recommendation to use Distinct because Union filters out duplicates.

var query = null; 

foreach(string item in yourString.Split(",")) 
{ 
    var newquery = db.Tablename.Where(x => x.FieldName.Contains(item));  
    if (query == null) {  
      query = query.union(newquery);    
    } else {  
      query = newquery;  
    }  
}  

var results = query.ToList(); 
MarkJ
hmm no this does not seem to work for me. I get the error:InnerException = {"The text data type cannot be selected as DISTINCT because it is not comparable.The text data type cannot be selected as DISTINCT because it is not comparable."}
Tim B James
I think that means the types don't implement IComparable? Does that sound right?
MarkJ
Actually I was wrong: you don't need to use Distinct, Union already filters out duplicates
MarkJ