Ich habe eine sehr große Bibliothek in einer SharePoint Online-Umgebung:> 3000 (Dokumentensätze) im Stammordner und mehr als 7000 (Dokumentensätze, Ordner und Dokumente) insgesamt. Das System basiert hauptsächlich auf benutzerdefiniertem Code: C # CSOM.
In Bezug auf die Leistung würde das System stark davon profitieren, jedes Mal Teilmengen des gesamten Datensatzes und nicht die gesamten 7000 Elemente abzufragen (meine derzeitige Lösung lädt Stapel von 5000 Elementen in eine ListItemCollection: in meinem Fall zuerst 5000 und dann 2000, und dann wird die Abfrage von LINQ durchgeführt), wobei insbesondere zu berücksichtigen ist, dass bestimmte Vorgänge direkt an bestimmte Ansichten gebunden sind.
Ich versuche die folgende Implementierung, wie sie in einem Kommentar zu einem anderen -Thread zu finden ist.
Microsoft.SharePoint.Client.List list = ctx.Web.Lists.GetByTitle(ListName); ctx.Load(list); ctx.ExecuteQuery(); Microsoft.SharePoint.Client.View view = list.Views.GetByTitle(viewName); ctx.Load(view); ctx.ExecuteQuery(); CamlQuery query = new CamlQuery(); query.ViewXml = view.ViewQuery; ListItemCollection items = list.GetItems(query); ctx.Load(items); ctx.ExecuteQuery();
Mein Problem ist, dass die ListItemCollection mit allen Elementen in der Stammsammlung (3000) gefüllt wird, wenn die ausgewählten Ansichten aus höchstens 60 Elementen bestehen.
Die view.ViewQuery wird mit folgendem Wert gefüllt:
"<GroupBy Collapse=\"FALSE\" GroupLimit=\"30\"><FieldRef Name=\"CurrentStatus\" /></GroupBy><OrderBy><FieldRef Name=\"CurrentStatus\" Ascending=\"FALSE\" /><FieldRef Name=\"Stage\" /></OrderBy><Where><And><Eq><FieldRef Name=\"Stage\" /><Value Type=\"Text\">Confirm Container</Value></Eq><Eq><FieldRef Name=\"PastTransition\" /><Value Type=\"Boolean\">0</Value></Eq></And></Where>"
Soll der obige Code funktionieren? Wenn ja, was ist falsch? Wenn nicht, welche andere Lösung erreicht dasselbe?
Kommentare
- Wie sieht die ViewQuery aus? Gefällt mir?
Antwort
Ziehen Sie CAML aus der Ansicht, weil Benutzer möglicherweise die Details des Filters aktualisieren? Wenn nicht, ist es wahrscheinlich der bessere Weg, die Abfrage manuell abzurufen.
Probieren Sie es aus:
query.ViewXml ="<View Scope=\"Recursive\"><Query><Where><And><Eq><FieldRef Name=\"Stage\" /><Value Type=\"Text\">Confirm Container</Value></Eq><Eq><FieldRef Name=\"PastTransition\" /><Value Type=\"Boolean\">0</Value></Eq></And></Where></Query></View>"
Da Ihre Liste> 7.000 Elemente enthält, müssen Sie auch sicherstellen, dass eines oder beide Elemente vorhanden sind der Spalten Stage und PastTransition werden indiziert. Kann davon abhängen, welche die kleinere Teilmenge der Daten zurückgibt und in welcher Reihenfolge sie ausgewertet werden.
Möglicherweise müssen Sie auch „RecursiveAll“ anstelle von „Recursive“ ausführen, je nachdem, ob Sie Ordner zurückgeben möchten / müssen. Aufzählung des Ansichtsbereichs anzeigen: https://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spviewscope.aspx
Hiermit erhalten Sie die gefilterte Liste. Von dort aus kann Ihr Code die zurückgegebenen Artikel gruppieren / bestellen.
Update
Da Abfragedetails dynamisch aus vorhandenen Ansichten abgeglichen werden müssen (gemäß Ihrem Feedback unten), können Sie den Inhalt von aus der vorhandenen view.ViewQuery ziehen und einfügen in die Ansicht XML oben. Dadurch wird die Abfrage entfernt und auf Listen> 5k ausgeführt.
Eine vollständig gebackene Lösung finden Sie in Jürgens Code.
Kommentare
- Das funktioniert so. Bedeutet das, dass Das Einrichten einer CAML-Abfrage und das Filtern nach indizierten Spalten mit einem abfragbaren Datensatz von mehr als 5000 Elementen stürzt nicht ab, wenn das zurückgegebene Ergebnis weniger als 5000 beträgt. Dies ist eine Problemumgehung, aber keine Lösung. Gibt es keine Möglichkeit, diese zu erhalten Ich möchte, dass die Abfrage dynamisch aus mehreren Ansichten erstellt wird und nicht jedes Mal die Ansichtskonfiguration in der CAML-Abfrage neu erstellt werden muss, wenn dies möglich ist. Dies ist jedoch bereits ein sehr guter Anfang! Also danke viel 🙂
- @JurgenCuschieri: Es sollte gut funktionieren, wenn mehr als 5K Listenelemente vorhanden sind. Ich bin mir nicht sicher, ob ich ' Ihren Anwendungsfall vollständig verstehe, aber Wenn Sie die Filterdetails dynamisch aus der Ansicht (oder den Ansichten) ziehen möchten, können Sie dies wahrscheinlich tun, indem Sie die Abfrage < > Teil der Ansicht ' s CAML und dynamisches Injizieren in < View Scrope = " Recusive " > < / View >.
- Ich ' werde das versuchen und zu Ihnen zurückkehren. Um es ein bisschen klarer zu machen, habe ich ein System mit vielen verschiedenen Abfragen. Die CAML-Abfrage wird verwendet, um Stapel von 5000 Elementen in eine Listenelement-Sammlung zu laden. LINQ wird verwendet, um die resultierende ListItemCollection abzufragen. Es ist unnötig zu erwähnen, dass der Vorgang lange dauert, bis ein Ergebnis zurückgegeben wird. Jedes (oder fast jedes) Szenario ist theoretisch an eine Ansicht gebunden. Dies bedeutet, dass der abfragbare Datensatz auf die gleichen Ansichtsergebnisse minimiert werden kann. Wenn also die Caml-Abfrage automatisch aus der Abfrage der Ansicht ' automatisch ausgefüllt werden kann – sinnvoller, nein?
- definieren die Ansichten bestimmte Phasen innerhalb eines Kundenunternehmens ' Geschäftsprozess. Diese CAML-Abfrageoperationen, die speziell innerhalb einer Phase verwendet werden, können daher dieselbe Abfrage wie die Ansicht verwenden. Dadurch wird der abfragbare Datensatz verfeinert, anstatt jedes Mal alle Elemente in der Liste zu verwenden.
- Großartig! Ich bin froh, dass es geklappt hat. Wir SharePoint-Entwickler müssen zusammenhalten … 🙂
Antwort
Das Folgende ist meine endgültige Lösung. basierend auf der Antwort von @Jim Barntish.
Microsoft.SharePoint.Client.List list = ctx.Web.Lists.GetByTitle(ListName); ctx.Load(list); ctx.ExecuteQuery(); Microsoft.SharePoint.Client.View view = list.Views.GetByTitle(viewName); ctx.Load(view); ctx.ExecuteQuery(); CamlQuery query = new CamlQuery(); query.ViewXml = view.ViewQuery; int pFrom = query.ViewXml.IndexOf("<Where>") + "<Where>".Length; int pTo = query.ViewXml.LastIndexOf("</Where>"); string whereClause = query.ViewXml.Substring(pFrom, pTo - pFrom); string queryStr = "<View Scope=\"Recursive\"><Query><Where>" + whereClause + "</Where></Query></View>"; query.ViewXml = queryStr; ListItemCollection items = list.GetItems(query); ctx.Load(items); ctx.ExecuteQuery();