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
yii\base\ErrorException
Copied! Copy Stacktrace Search Stackoverflow Search Google Error

PHP Core Warningyii\base\ErrorException

PHP Startup: Unable to load dynamic library 'mongodb.so' (tried: /usr/lib64/php/modules/mongodb.so (/usr/lib64/php/modules/mongodb.so: cannot open shared object file: No such file or directory), /usr/lib64/php/modules/mongodb.so.so (/usr/lib64/php/modules/mongodb.so.so: cannot open shared object file: No such file or directory))

$_GET = [
    'id' => '358600',
    'url' => 'sql-generated-by-entityframework-startswith-contains-plan-altering-escape',
];

$_COOKIE = [
    '_csrf-frontend' => '41e2733e744717fb1bc411f766136a66240f1237d0e84f440fb726d73c55b882a:2:{i:0;s:14:"_csrf-frontend";i:1;s:32:"I3vAKp7Vw6q14zoBYUsUaFDtLrbUDy7l";}',
    'advanced-frontend' => '525d7876cf0a3c7dbe7f21293397ce25',
];

$_SESSION = [
    '__flash' => [],
];