Kraft Entity Framework SQL-Parametrisierung für bessere SQL-proc-cache Wiederverwendung

Entity Framework scheint immer die Konstanten verwenden, die in der generierten SQL für die Werte bereitgestellt werden, um Skip() und Take().

In der ultra-Vereinfachtes Beispiel unten:

int x = 10;
int y = 10;

var stuff = context.Users
    .OrderBy(u => u.Id)
    .Skip(x)
    .Take(y)
    .Select(u => u.Id)
    .ToList();

x = 20;

var stuff2 = context.Users
    .OrderBy(u => u.Id)
    .Skip(x)
    .Take(y)
    .Select(u => u.Id)
    .ToList();

der obige code erzeugt die folgenden SQL-Abfragen:

SELECT TOP (10) 
[Extent1].[Id] AS [Id]
FROM ( SELECT [Extent1].[Id] AS [Id], row_number() OVER (ORDER BY [Extent1].[Id] ASC) AS [row_number]
    FROM [dbo].[User] AS [Extent1]
)  AS [Extent1]
WHERE [Extent1].[row_number] > 10
ORDER BY [Extent1].[Id] ASC

SELECT TOP (10) 
[Extent1].[Id] AS [Id]
FROM ( SELECT [Extent1].[Id] AS [Id], row_number() OVER (ORDER BY [Extent1].[Id] ASC) AS [row_number]
    FROM [dbo].[User] AS [Extent1]
)  AS [Extent1]
WHERE [Extent1].[row_number] > 20
ORDER BY [Extent1].[Id] ASC

Was in 2 ad-hoc-Pläne Hinzugefügt, um die SQL-proc-cache mit 1 Einsatz jeder.

Was ich möchte, zu erreichen, ist für die Parametrisierung der Skip() und Take() Logik, damit die folgenden SQL-Abfragen generiert:

EXEC sp_executesql N'SELECT TOP (@p__linq__0) 
[Extent1].[Id] AS [Id]
FROM ( SELECT [Extent1].[Id] AS [Id], row_number() OVER (ORDER BY [Extent1].[Id] ASC) AS [row_number]
    FROM [dbo].[User] AS [Extent1]
)  AS [Extent1]
WHERE [Extent1].[row_number] > @p__linq__1
ORDER BY [Extent1].[Id] ASC',N'@p__linq__0 int,@p__linq__1 int',@p__linq__0=10,@p__linq__1=10

EXEC sp_executesql N'SELECT TOP (@p__linq__0) 
[Extent1].[Id] AS [Id]
FROM ( SELECT [Extent1].[Id] AS [Id], row_number() OVER (ORDER BY [Extent1].[Id] ASC) AS [row_number]
    FROM [dbo].[User] AS [Extent1]
)  AS [Extent1]
WHERE [Extent1].[row_number] > @p__linq__1
ORDER BY [Extent1].[Id] ASC',N'@p__linq__0 int,@p__linq__1 int',@p__linq__0=10,@p__linq__1=20

Diese Ergebnisse in 1 Vorbereiteten plan Hinzugefügt, um die SQL-proc-cache mit 2 verwendet.

Habe ich einige ziemlich komplexe Abfragen und erlebe erheblichen overhead (auf der Seite SQL Server) auf dem ersten Lauf, und viel schnellere Ausführung auf die nachfolgende ausgeführt wird (da Sie es verwenden können, der plan cache). Beachten Sie, dass diese erweiterte Abfragen bereits verwenden von sp_executesql als die anderen Werte werden parametriert, so bin ich nicht besorgt über diesen Aspekt.

Den ersten Satz von generierten Abfragen über grundsätzlich bedeutet jede Paginierung Logik erstellt einen neuen Eintrag in der plan-cache für jede Seite, Blähungen den cache und die plan-Generierung Gemeinkosten werden die Kosten für jede Seite.

Kann ich Kraft Entity Framework zur Parametrisierung der Werte? Ich habe bemerkt, für andere Werte, z.B. in Where Klauseln, manchmal ist es parametrisiert Werte, und manchmal ist es verwendet Konstanten.

Bin ich völlig out to lunch? Gibt es einen Grund, warum Entity Framework vorhandene Verhalten besser als das Verhalten, das ich mir Wünsche?

Edit:
Falls es relevant ist, ich sollte erwähnen, dass ich mit Entity Framework 4.2.

Edit 2:
Diese Frage ist nicht ein Duplikat von Entity Framework/Linq to SQL: Skip & Nehmen, die lediglich fragt, wie um sicherzustellen, dass Skip und Take ausführen, die in SQL statt auf dem client. Diese Frage bezieht sich auf die Parametrisierung dieser Werte.

  • Dieser link erklärt, wie Sie mithilfe von Linq-mit SQL-Parametern Sie müssen nach unten scrollen, um den unteren link, um zu sehen, die Erklärung und Beispiel LinqPad-site - linqpad.net/WhyLINQBeatsSQL.aspx
  • Tolle Beobachtung. Ich normalerweise nicht verwenden, EF-für "echte" Projekte, die nur spielen, um mit kleinen Sachen, und nie bemerkt, dass dieses Verhalten vor. Wenn EF nicht parametrisieren alles, was es kann, dann ich halte das für einen riesigen Fehler.
  • gute Frage - man könnte meinen, Sie hatte optimiert für eine mögliche Wiederverwendung des plans
  • KRAZE: dein link erklärt, dass Linq kann die Verwendung von parametrisierten SQL, aber es gibt nichts über Steuern, wenn es passiert.
  • Ich entschuldige mich über das GWB habe ich deine Frage missverstanden..
  • Mögliche Duplikate von Entity Framework/Linq to SQL: Skip & Take
  • der verlinkte Frage ist anders, als es nur verlangt, um sicherzustellen, dass die Take-und Skip-Ausführung auf der Datenbank statt auf dem client. Es geht nicht, der zusätzliche Schritt ist, sicherzustellen, dass die Take-und Skip verwenden Sie die Parametrierung für proc cache wiederverwenden.

InformationsquelleAutor GWB | 2012-02-08
Schreibe einen Kommentar