Posted by DevExpert on September 25th, 2009
One of the requirements of one of my recent projects was to implement a search page which allowed the user to enter a search term that supported wildcards. The search term could contain any number of wildcards in any position within that term.
If you’ve done anything like this before, you probably know there’s nothing built-in to LINQ that supports this type of behavior. Sure, you could use a combination of String.StartsWith, String.EndsWith, or String.Contains, but this could quickly become too cumbersome if there are many wildcards and/or they are scattered throughout the search term. Let’s look at a couple simple examples to illustrate…
Pretend for a second I was doing this in SQL, and I needed to get all values that start with the letter T. I would do this:
The .NET/LINQ equivalent would be this:
Not too difficult. However, what if you wanted to do the SQL-equivalent of this:
You’d have do a little creative parsing. It gets even worse when you as the developer doesn’t know what search term will be entered, how many wildcards will be included, and where in the term they appear. It all has to be dynamic.
I did a little poking around to see if anyone has done this before, and the only thing I could find was recommendations on using StartsWith/EndsWith/Contains, which I already ruled out. I also found the SqlMethods.Like() method which sounded perfect. However after further research, discovered it can only be used on an entity directly retrieved from a DataContext, such as this:
If you try to use the SqlMethods.Like() method on anything except a DataContext’s Table<T>, you’ll get the following message:
“Method ‘Boolean Like(System.String, System.String)’ cannot be used on the client; it is only for translation to SQL.”
So much for that. I decided to write my own extension method. I figured I could write one fairly easily using a regular expression, and I was right! I checked out a trusty RegEx cheat sheet and found the following relevant metacharacters:
- ^ Indicates the start of a string
- $ Indicates the end of a string
- * Indicates zero or more of previous expression
Knowing this, I wrote the following extension method:
Which I can then use like this:
I can even simplify this by wrapping it up in another extension method:
Now all I have to do is the following:
Finally, a quick usage example to prove it works:
Hopefully you’ll find this useful!