Hilfe für die Optimierung von Linq Datenextraktion benötigt
-
22-07-2019 - |
Frage
Ich bin Abrufen von Daten aus allen drei Tabellen gleichzeitig Netzwerk-Latenz zu vermeiden. die Daten-Abruf ist ziemlich schnell, aber wenn ich eine Schleife durch die Ergebnisse wird viel Zeit verwendet
Int32[] arr = { 1 };
var query = from a in arr
select new
{
Basket = from b in ent.Basket
where b.SUPERBASKETID == parentId
select new
{
Basket = b,
ObjectTypeId = 0,
firstObjectId = "-1",
},
BasketImage = from b in ent.Image
where b.BASKETID == parentId
select new
{
Image = b,
ObjectTypeId = 1,
CheckedOutBy = b.CHECKEDOUTBY,
firstObjectId = b.FIRSTOBJECTID,
ParentBasket = (from parentBasket in ent.Basket
where parentBasket.ID == b.BASKETID
select parentBasket).ToList()[0],
},
BasketFile = from b in ent.BasketFile
where b.BASKETID == parentId
select new
{
BasketFile = b,
ObjectTypeId = 2,
CheckedOutBy = b.CHECKEDOUTBY,
firstObjectId = b.FIRSTOBJECTID,
ParentBasket = (from parentBasket in ent.Basket
where parentBasket.ID == b.BASKETID
select parentBasket),
}
};
//Exception handling
var mixedElements = query.First();
ICollection<BasketItem> basketItems = new Collection<BasketItem>();
//Here 15 millis has been used
//only 6 elements were found
if (mixedElements.Basket.Count() > 0)
{
foreach (var mixedBasket in mixedElements.Basket){}
}
if (mixedElements.BasketFile.Count() > 0)
{
foreach (var mixedBasketFile in mixedElements.BasketFile){}
}
if (mixedElements.BasketImage.Count() > 0)
{
foreach (var mixedBasketImage in mixedElements.BasketImage){}
}
//the empty loops takes 811 millis!!
Lösung
Warum stören Sie die Zählungen vor den foreach-Anweisungen zu überprüfen? Wenn es keine Ergebnisse gibt, wird die foreach nur sofort beenden.
Ihre Anfragen sind eigentlich alle latenten werden - werden sie als ausgeführt werden, und wenn Sie für die Daten fragen. Vergessen Sie nicht, dass Ihre äußerste Abfrage ein LINQ to Objects-Abfrage ist. es zurückkehrt gerade das Ergebnis des Aufrufs ent.Basket.Where(...).Select(...)
etc ... das ist eigentlich nicht die Abfrage ausführen
Ihr Plan alle drei Abfragen in einem Rutsch zu tun, ist nicht wirklich funktioniert. Indem jedoch separat für die Zählung zu fragen, können Sie tatsächlich jede Datenbankabfrage zweimal werden die Ausführung -. Nur ein einziges Mal die Zählung bekommen und einmal für die Ergebnisse
Ich empfehle, dass Sie in diesem Code der „Optimierungen“ loszuwerden, die es viel komplizierter und langsamer machen als nur den einfachsten Code schreiben Sie können.
Ich weiß nicht, von irgendeiner Weise LINQ to SQL zu bekommen (oder LINQ to EF) mehrere Abfragen in einem einzigen Aufruf auszuführen -. Aber dieser Ansatz sicherlich wird es nicht tun würde
Eine weitere kleine Andeutung, die in diesem Fall irrelevant ist, kann aber in LINQ to Objects nützlich sein - wenn Sie wollen herausfinden, ob es in einer Sammlung alle Daten ist, benutzen Sie einfach Any()
statt Count() > 0
- auf diese Weise als stoppen sobald er etwas gefunden hat.
Andere Tipps
Sie verwenden IEnumerable
in der foreach-Schleife. Implementationen haben nur Daten zu erstellen, wenn es gefragt wird. Ich würde auf diese Weise deuten darauf hin, dass der obige Code Ihre Daten lazily zugreift - das heißt, nur wenn Sie die Begriffe aufzuzählen
Count()
nennen.)
Setzen Sie einen System.Diagnostics.Stopwatch
um den Anruf zu Count()
und zu sehen, ob das den Großteil der Zeit ist, nehmen Sie sehen.
Ich kann hier nicht weiter kommentieren, weil Sie nicht die Art von ent
in Ihrem Codebeispiel angeben.