SQL generiert von EntityFramework StartsWith () enthält einen Plan, der ESCAPE '~' (Tilde) ändert

8

Mit EntityFramework führt die Klausel .OrderBy(x => x.Title.StartsWith("foo")) zu SQL WHERE (Title LIKE 'foo%' ESCAPE '~') .

Wenn ich den Ausführungsplan für die vollständige Abfrage anschaue, sehe ich, dass ich einen anderen Plan (einen, der den nicht gruppierten Index der Spalte verwendet) bekomme, wenn ich ESCAPE '~' entferne.

Warum versucht EF, einer Zeichenkette zu entkommen, die sie nicht benötigt, und wie kann ich sie stoppen?

    
stovroz 10.12.2013, 13:40
quelle

2 Antworten

11

Der überflüssige ESCAPE kann sicherlich die Kardinalitätsschätzungen ändern und einen anderen Plan geben. Obwohl lustigerweise fand ich, dass es in diesem Test mehr Genauigkeit als weniger macht!

%Vor%

Ohne Escape

%Vor%

Mit Escape

%Vor%

Kurz vor der Aktualisierung auf eine neuere Version von EF oder dem Schreiben Ihrer eigenen benutzerdefinierten DbProviderManifest -Implementierung Ich denke, Sie haben kein Glück bei Ihrem Versuch, ESCAPE zu entfernen.

Das Übersetzen von String.StartsWith , String.EndsWith und String.Contains zu LIKE anstelle von CHARINDEX war neu in EF 4.0

Betrachtet man die Definition von System.Data.Entity, Version=4.0.0.0 im Reflektor, scheint die relevante Funktion (in System.Data.SqlClient.SqlProviderManifest )

zu sein %Vor%

Die Signatur für diese Methode lautet

%Vor%

Es ist also nur fest codiert, immer escape zu verwenden und das Flag, das zurückgegeben wird, wird ignoriert.

Diese Version von EF fügt also nur% ESCAPE '~' an alle LIKE Abfragen an.

Dies scheint etwas zu sein, das in der neuesten Codebasis verbessert wurde.

Die Definition von SqlFunctionCallHandler.TranslateConstantParameterForLike ist

%Vor%

SqlProviderManifest.EscapeLikeText ist derselbe Code wie bereits gezeigt. Beachten Sie, dass es nun false als zweiten Parameter übergibt und das Ausgabeparameter-Flag verwendet, um nur den ESCAPE bei Bedarf anzuhängen.

    
Martin Smith 10.12.2013, 21:27
quelle
1

Ab Entity Framework 6.2 gibt es die zusätzliche Unterstützung für .Like() als Teil von DbFunctions .

Nun können Sie das tun:

%Vor%

Weitere Informationen: Ссылка

    
Korayem 03.10.2017 07:25
quelle