1

Scenario: I have a list of keywords, and I want to add a Linq Where clause to check if a Product object's description field contains ALL three keywords.

I am trying to add the following where clause to my query:

 query = query.Where(product => keywords.All(product.Description.Contains));

query: is an IQueryable(Product) keywords: is a List Description: is a field in a product.

When I try to run this code I get an exception .NET Framework Data Provider error 1025.

I have also tried creating the expression seperately like so, as per other posts:

 Expression<Func<Product, bool>> expr = product => keywords.All(product.Description.Contains);
            query = query.Where(expr);

This gives the same error.

PS: Here is how I am declaring my IQueryable, just in case:

 var query = from product in Entity.Products select product;
  • 5
    Please show the *full* exception details. – Jon Skeet Nov 25 '13 at 08:06
  • This looks similar to this: http://stackoverflow.com/q/9513284/1039947 - just try changing `keywords.All(product.Description.Contains)` to `keywords.All(word => product.Description.Contains(word))` – kmp Nov 25 '13 at 08:20

1 Answers1

0

If you are using EF I doubt this code will work this way. I tested this with a generic list in memory, and as expected it works properly.

Try adding the where clauses one at a time for each keyword. This will work on the DB side. Providers only know how to match on specific words (e.g. Contains, StartsWith) in certain contexts and written certain ways.

var query = // your query 

// this is easy since you are doing an "AND"
foreach(var word in keywords) {
    var w = word;  // need this! really!
    query = query.Where(product => product.Description.Contains(w));
}

Here is the reason we need the variable "w":

Since you ended up using the 'for', here is how that would look for others who might see this answer:

for(var i = 0; i < keywords.Length - 1; i ++) {
    query = query.Where(x => x.Description.Contains(keywords[i]));
}
Community
  • 1
  • 1
Andrew
  • 8,322
  • 2
  • 47
  • 70
  • I am going with your suggestion to add a clause for each keyword using a foreach loop, which I thank you for, by the way. However, it is returning records that match the LAST keyword only and ignoring the first few. foreach (string keyword in keywords) { query = query.Where(product => product.Description.Contains(keyword)); } basically, the result is brining up records that contain the LAST keyword instead of all – Joseph Grech Nov 25 '13 at 08:29
  • No problem. We do that *a lot* when making dynamic queryies where a user can search by >1 parameter (e.g. a search form) – Andrew Nov 25 '13 at 08:31
  • Ok, fixed it. I forgot to add the temporary variable. You need that or only the last member will be captured by LINQ (so you will get three where clauses for the same variable. – Andrew Nov 25 '13 at 08:36
  • I switched from using a foreach to a traditional forloop and accessing the keyword by keyword[i] and it worked! – Joseph Grech Nov 25 '13 at 08:38
  • 1
    Yeah, a traditional `for` loop will work fine too. The issue that causes the "w" variable to be needed will be fixed in C# 5, according to Mr. Lippert :) Priorities may change, though. – Andrew Nov 25 '13 at 08:50