I have this code:
DbSet<TableName> table = ...// stored reference
var items = from n in table where
n.Name.ToUpper().Contains(searchString.ToUpper().Trim())
select n;
WriteToLog( items.ToString() );
The last line outputs the generated SQL. Here's what I get:
SELECT
[Extent1].[Name] AS [Name],
// all the other columns follow
FROM (SELECT
[TableName].[Name] AS [Name],
// all the other columns follow
FROM [dbo].[TableName] AS [TableName]) AS [Extent1]
WHERE ( CAST(CHARINDEX(LTRIM(RTRIM(UPPER(@p__linq__0))), UPPER([Extent1].[Name])) AS int)) > 0
You see, there's SELECT-from-SELECT although it's completely redundant - one SELECT would be just enough. The code using EF runs longer than half a minute and time out on that query although the table is rather small.
Why is this overengineered SQL query generated and how do I make EF generate a better query?
searchString.ToUpper().Trim()should be resolved outside of the query so that you don't offload that work onto sql serverWHEREclause - It will totally obfuscate any available indexes. If you were able to refactor your data to not require use ofUPPERandCONTAINSyou'd have a much more SQL friendly query. That may not be possible, but using either of these is always going to have massive performance consequences.) [You're effectively doingName LIKE '%xxx%'and anyone experienced with SQL will tell you that is the problem.]