views:

2147

answers:

3

We're trying to implement the "LIKE" operator in Entity Framework for our entities with string fields, but it doesn't appear to be supported. Has anyone else tried to do something like this?

This blog post summarizes the issue we're having. We could use contains, but that only matches the most trivial case for LIKE. Combining contains, startswith, endswith, and indexof gets us there, but requires a translation between standard wildcards and Linq to Entities code.

+6  A: 

I don't know anything about EF really, but in LINQ to SQL you usually express a LIKE clause using String.Contains:

where entity.Name.Contains("xyz")

translates to

WHERE Name LIKE '%xyz%'

(Use StartsWith and EndsWith for other behaviour.)

I'm not entirely sure whether that's helpful, because I don't understand what you mean when you say you're trying to implement LIKE. If I've misunderstood completely, let me know and I'll delete this answer :)

Jon Skeet
please note that "WHERE Name LIKE '%xyz%'" will be unable to use an index, so if table is huge it might not perform that well...
Mitch Wheat
Well, we'd like to be able to match on *blah *blah* foo*bar foo?bar ?foo*bar? and other complex patterns. Our current approach is similar to what you mentioned, we would convert those queries into operations using contains, indexof, startswith, endswith, etc. I was just hoping that there was a more general-purpose solution.
brien
Not that I'm aware of - I suspect that complex patterns end up being more db-specific, and hard to express in a general way.
Jon Skeet
@Jon Skeet: to my best knowledge LIKE functionality is in ANSI standard and it is pretty much the same in SQL Server, Oracle, and DB2.
AlexKuznetsov
@AlexKuznetsov: I seem to remember having some issues with compatibility between SQL Server and Oracle in the past, particularly when it comes to escaping. I had to write a Hibernate operator to cope with % being in the query string, and the Oracle and SQL Server implementations were different. It could be that I was missing a trick, or that the world has improved since then.
Jon Skeet
+1 I just tried this out on EF 3.5 on SQL Server, and it works at least in that combination.
Mark Seemann
+2  A: 

It is specifically mentioned in the documentation as part of Entity SQL. Are you getting an error message?

// LIKE and ESCAPE
// If an AdventureWorksEntities.Product contained a Name 
// with the value 'Down_Tube', the following query would find that 
// value.
Select value P.Name FROM AdventureWorksEntities.Product 
    as P where P.Name LIKE 'DownA_%' ESCAPE 'A'

// LIKE
Select value P.Name FROM AdventureWorksEntities.Product 
    as P where P.Name like 'BB%'

http://msdn.microsoft.com/en-us/library/bb399359.aspx

Robert Harvey
I would be tempted to stay away from Entity SQL in case you wanted to move away from EF in the future. Play it safe and stick with the Contains(), StartsWith() and EndsWith() options in the original response instead.
Stephen Newman
That compiles fine, but fails at runtime.
brien
The code I posted fails at runtime? It comes from the Microsoft link.
Robert Harvey
Error message?..
Robert Harvey
I edited the question with a link to a blog post describing the same issue we're having.
brien
Looks like Contains() is your ticket. But as Jon Skeet pointed out, you may have to drop down to some actual SQL manipulating the database directly, if Contains doesn't meet your needs.
Robert Harvey
Another relevant StackOverflow post: http://stackoverflow.com/questions/835790/how-to-do-sql-like-in-linq
Robert Harvey
+1  A: 

re: "we'd like to be able to match on blah blah foobar foo?bar ?foo*bar? and other complex patterns." I haven't actually tried this (haven't needed to yet), but have you tried using System.Text.RegularExpressions.RegEx?

th2tran
A regular expression would run on the web server, not the DB. Basically, it would involve returning the entire table from SQL Server, then filtering. That would work for some small cases, but we need to search large(ish) volumes of data. Good suggestion, though, that was my first thought also.
brien