Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The superfluous <code>ESCAPE</code> can certainly alter cardinality estimates and give a different plan. Though funnily enough I found it make it more accurate rather than less in this test!</p> <pre><code>CREATE TABLE T ( Title VARCHAR(50), ID INT IDENTITY, Filler char(1) NULL, UNIQUE NONCLUSTERED (Title, ID) ) INSERT INTO T (Title) SELECT TOP 1000 CASE WHEN ROW_NUMBER() OVER (ORDER BY @@SPID) &lt; 10 THEN 'food' ELSE LEFT(NEWID(), 10) END FROM master..spt_values </code></pre> <p>Without <code>Escape</code></p> <pre><code>SELECT * FROM T WHERE (Title LIKE 'foo%') </code></pre> <p><img src="https://i.stack.imgur.com/2M83X.png" alt="enter image description here"></p> <p>With <code>Escape</code></p> <pre><code>SELECT * FROM T WHERE (Title LIKE 'foo%' ESCAPE '~') </code></pre> <p><img src="https://i.stack.imgur.com/cU0Ma.png" alt="enter image description here"></p> <p>Short of upgrading to a more recent version of EF or writing your own custom <code>DbProviderManifest</code> implementation I think you are out of luck in your attempt at removing <code>ESCAPE</code>.</p> <p>Translating <code>String.StartsWith</code>, <code>String.EndsWith</code> and <code>String.Contains</code> to <code>LIKE</code> rather than <code>CHARINDEX</code> was <a href="http://blogs.msdn.com/b/adonet/archive/2009/10/22/new-features-in-entity-framework-impacting-providers.aspx" rel="noreferrer">new in EF 4.0</a></p> <p>Looking at the definition of <code>System.Data.Entity, Version=4.0.0.0</code> in reflector the relevant function seems to be (in <code>System.Data.SqlClient.SqlProviderManifest</code>)</p> <pre><code>public override string EscapeLikeArgument(string argument) { bool flag; EntityUtil.CheckArgumentNull&lt;string&gt;(argument, "argument"); return EscapeLikeText(argument, true, out flag); } </code></pre> <p>The signature for that method is</p> <pre><code>internal static string EscapeLikeText(string text, bool alwaysEscapeEscapeChar, out bool usedEscapeChar) { usedEscapeChar = false; if (((!text.Contains("%") &amp;&amp; !text.Contains("_")) &amp;&amp; (!text.Contains("[") &amp;&amp; !text.Contains("^"))) &amp;&amp; (!alwaysEscapeEscapeChar || !text.Contains("~"))) { return text; } StringBuilder builder = new StringBuilder(text.Length); foreach (char ch in text) { switch (ch) { case '%': case '_': case '[': case '^': case '~': builder.Append('~'); usedEscapeChar = true; break; } builder.Append(ch); } return builder.ToString(); } </code></pre> <p>So it is just hardcoded to always use escape and the flag that is returned is ignored.</p> <p>So that version of EF just appends the <code>ESCAPE '~'</code> to all <code>LIKE</code> queries.</p> <p>This seems to be something that has been improved in the most recent code base.</p> <p>The definition of <a href="http://entityframework.codeplex.com/SourceControl/latest#src/EntityFramework.SqlServer/SqlGen/SqlFunctionCallHandler.cs" rel="noreferrer">SqlFunctionCallHandler.TranslateConstantParameterForLike</a> is</p> <pre><code>// &lt;summary&gt; // Function to translate the StartsWith, EndsWith and Contains canonical functions to LIKE expression in T-SQL // and also add the trailing ESCAPE '~' when escaping of the search string for the LIKE expression has occurred // &lt;/summary&gt; private static void TranslateConstantParameterForLike( SqlGenerator sqlgen, DbExpression targetExpression, DbConstantExpression constSearchParamExpression, SqlBuilder result, bool insertPercentStart, bool insertPercentEnd) { result.Append(targetExpression.Accept(sqlgen)); result.Append(" LIKE "); // If it's a DbConstantExpression then escape the search parameter if necessary. bool escapingOccurred; var searchParamBuilder = new StringBuilder(); if (insertPercentStart) { searchParamBuilder.Append("%"); } searchParamBuilder.Append( SqlProviderManifest.EscapeLikeText(constSearchParamExpression.Value as string, false, out escapingOccurred)); if (insertPercentEnd) { searchParamBuilder.Append("%"); } var escapedSearchParamExpression = constSearchParamExpression.ResultType.Constant(searchParamBuilder.ToString()); result.Append(escapedSearchParamExpression.Accept(sqlgen)); // If escaping did occur (special characters were found), then append the escape character used. if (escapingOccurred) { result.Append(" ESCAPE '" + SqlProviderManifest.LikeEscapeChar + "'"); } } </code></pre> <p><a href="https://entityframework.codeplex.com/SourceControl/latest#src/EntityFramework.SqlServer/SqlProviderManifest.cs" rel="noreferrer">SqlProviderManifest.EscapeLikeText</a> is the same code as already shown. Note that it now passes <code>false</code> as the second parameter and uses the output parameter flag to only append the <code>ESCAPE</code> where necessary.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload