ich beheben hat den folgenden Code, der sie schlecht benimmt:Wie super langsam EF/LINQ-Abfrage Ausführen mehr SQL-Anweisungen
TPM_USER user = UserManager.GetUser(context, UserId);
var tasks = (from t in user.TPM_TASK
where t.STAGEID > 0 && t.STAGEID != 3 && t.TPM_PROJECTVERSION.STAGEID <= 10
orderby t.DUEDATE, t.PROJECTID
select t);
Die erste Zeile, wird UserManager.GetUser
nur eine einfache Suche in der Datenbank, um die richtigen zu bekommen TPM_USER
aufnehmen. Die zweite Zeile verursacht jedoch alle Arten von SQL-Chaos.
Als erstes werden hier zwei SQL-Anweisungen ausgeführt. Die erste packt jede einzelne Zeile in TPM_TASK
, die diesem Benutzer verknüpft ist, die manchmal Zehntausende von Zeilen:
SELECT
-- Columns
FROM TPMDBO.TPM_USERTASKS "Extent1"
INNER JOIN TPMDBO.TPM_TASK "Extent2" ON "Extent1".TASKID = "Extent2".TASKID
WHERE "Extent1".USERID = :EntityKeyValue1
Diese Abfrage dauert etwa 18 Sekunden auf Benutzer mit vielen Aufgaben. Ich würde erwarten, dass die WHERE-Klausel auch die STAGEID-Filter enthält, die die Mehrheit der Zeilen entfernen würde.
Als nächstes scheint es eine neue Abfrage für jedes TPM_PROJECTVERSION
Paar in der Liste auszuführen oben:
SELECT
-- Columns
FROM TPMDBO.TPM_PROJECTVERSION "Extent1"
WHERE ("Extent1".PROJECTID = :EntityKeyValue1) AND ("Extent1".VERSIONID = :EntityKeyValue2)
Auch wenn diese Abfrage schnell ist, es mehr hundert Mal ausgeführt ist, wenn die Benutzer Aufgaben in einem ganzen Bündel hat von Projekten.
SELECT
-- Columns
FROM TPMDBO.TPM_USERTASKS "Extent1"
INNER JOIN TPMDBO.TPM_TASK "Extent2" ON "Extent1".TASKID = "Extent2".TASKID
INNER JOIN TPMDBO.TPM_PROJECTVERSION "Extent3" ON "Extent2".PROJECTID = "Extent3".PROJECTID AND "Extent2".VERSIONID = "Extent3".VERSIONID
WHERE "Extent1".USERID = 5 and "Extent2".STAGEID > 0 and "Extent2".STAGEID <> 3 and "Extent3".STAGEID <= 10
Die Abfrage oben in etwa 1 Sekunde laufen würde:
Die Abfrage Ich mag würde wäre so etwas wie aussehen zu erzeugen. Normalerweise könnte ich JOIN
mit der Methode Include
angeben. Dies scheint jedoch bei Eigenschaften nicht zu funktionieren. Mit anderen Worten, ich kann nicht:
from t in user.TPM_TASK.Include("TPM_PROJECTVERSION")
Gibt es eine Möglichkeit, diese LINQ-Anweisung zu optimieren? Ich verwende .NET4 und Oracle als Backend-DB.
Lösung:
Diese Lösung unten auf Kirks Vorschläge basiert, und arbeitet seit context.TPM_USERTASK
nicht direkt abgefragt werden können:
var tasks = (from t in context.TPM_TASK.Include("TPM_PROJECTVERSION")
where t.TPM_USER.Any(y => y.USERID == UserId) &&
t.STAGEID > 0 && t.STAGEID != 3 && t.TPM_PROJECTVERSION.STAGEID <= 10
orderby t.DUEDATE, t.PROJECTID
select t);
Es tut Ergebnis in einer verschachtelten SELECT
anstatt TPM_USERTASK
abfragt direkt, aber es scheint ziemlich effizient dennoch.
Leider wird diese Idee nicht funktionieren. 'TPM_TASK' hat keine' USERID'-Eigenschaft. Benutzer beziehen sich auf Tasks über die Tabelle "TPM_USERTASK", die Sie nicht direkt abfragen können, da sie in einer Viele-zu-Viele-Beziehung verwendet wird. Vielleicht wäre es besser, eine Ansicht in der Datenbank zu erstellen oder so? –
Sie können sicherlich die Abfrage auch gegen 'TPM_USERTASK' schreiben. Ich bin mir nicht sicher, wie genau dein Schema aufgebaut ist, aber etwas in der Art von 'where t.TPM_TASK.Any (y => y.USERID == t.USER)' oder benutze 'join', um das zu holen viel zu viel. Sie tun definitiv nicht mit Ansichten zu tun, um dies zu erreichen. –
Okay, mit dieser Idee zu tun .. Ich werde Sie in ein paar Minuten wissen .. –