Convenient CLR Methods aren't always the best for LINQ to Entities

Not all CLR methods can be used when building LINQ to Entities or LINQ to SQL queries. The method needs to be something that can be expressed in the native query language. So if you have a date field, you can't use ToShortDateString in the query since there is no equivalent. You'll get runtime exceptions when you use these as the query compiler goes to work.

There are others that work, but you may not want them.

Case in point is doing a query to search on the first letter of a property.

String.StartsWith

VB

From con In context.Contacts _
                     Where con.LastName.StartsWith("S")

C#

from con in PEF.Contacts
                    where con.LastName.StartsWith("S")
                    select con

Both render this WHERE clause in TSQL:

WHERE (CAST(CHARINDEX(N'S', [Extent1].[LastName]) AS int)) = 1

I've been told this will make DBAs run away screaming.

 

String.SubString

VB

From con In PEF.Contacts _
                     Where con.LastName.Substring(0, 1) = "S"

C#

from con in PEF.Contacts
                          where con.LastName.Substring(0, 1) == "S"
                          select con

These render this WHERE clause:

WHERE N'S' = (SUBSTRING([Extent1].[LastName], 0 + 1, 1))

 

Visual Basic's Left does the cleanest job

From con In PEF.Contacts _
                    Where Left(con.LastName, 1) = "S"

Gives us:

WHERE N'S' = (LEFT([Extent1].[LastName], 1))

Other options such as attempting to use an indexer (lastname(0) or lastname

 

Be careful out there.

#1 Kristofer Andersson on 9.22.2008 at 1:41 AM

Hi Julie,Just a FYI (but a noteworthy one): Linq-to-SQL does a _much_ better job than EF at translating Linq expressions such as the ones in your example into efficient SQL queries. For example, a .StartsWith("something") in the where clause of a linq query against a L2S data context is translated into a like clause that will be able to take advantage of indexes while the EF "cast(charindex" rules out the use of any indexes on the columns involved. (thus EF will make "DBAs run off screaming" while L2S won't in this case)(from cust in nd.Customers where cust.CompanyName.StartsWith("a") select cust).ToList<Customer>();...translates into...SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax], [t0].[PrimaryEmailAddress]FROM [dbo].[Customers] AS [t0]WHERE [t0].[CompanyName] LIKE @p0

#2 unruledboy on 9.22.2008 at 5:14 AM

hi, intersting article. I suggest that you try out the free linqpad util:http://www.linqpad.net/

#3 Julia Lerman on 9.25.2008 at 9:21 AM

LINQPad doesn't support LINQ to Entities, but thanks for the reminder! I hadn't checked recently.

Leave a Comment