Nicht unterstützte LINQ-Abfragen und zweiphasige Abfragen
Letzte Änderung: Donnerstag, 22. September 2011
Gilt für: SharePoint Foundation 2010
Inhalt dieses Artikels
Nicht unterstützte Abfragen
Zweiphasige Abfragen
Wenn die Unterscheidung keine Rolle spielt
In diesem Thema werden bestimmte Arten von LINQ-Abfragen (Language Integrated Query) behandelt, die vom LINQ to SharePoint-Anbieter nicht unterstützt werden. Außerdem wird beschrieben, wie ein zweiphasiger Prozess für Abfragen mit LINQ-Operatoren verwendet wird, die vom LINQ to SharePoint-Anbieter nicht in Collaborative Application Markup Language (CAML) übersetzt werden können.
Nicht unterstützte Abfragen
Manche Abfragen, die in der LINQ-Syntax von C# und Visual Basic verfügbar gemacht werden und die in bestimmten Kontexten für bestimmte Arten von Datenquellen problemlos ausgeführt werden, resultieren bei der Ausführung für die Daten in einer Microsoft SharePoint Foundation-Website zu einer inakzeptabel niedrigen Leistung. Solche Abfragen werden vom LINQ to SharePoint-Anbieter nicht unterstützt. Es handelt sich dabei um alle Abfragen, die mehr als eine separate Abfrage für die Inhaltsdatenbank benötigen. Wenn z. B. eine Abfrage für die Tabelle A für jede Zeile von Tabelle A eine separate Abfrage für Tabelle B erfordert, wird die Abfrage für Tabelle A nicht unterstützt. Entsprechend wird wie im folgenden Beispiel veranschaulicht die Verwendung des LINQ-Schlüsselworts union nicht unterstützt, und es würde eine Ausnahme gemeldet, da separate Abfragen für zwei Listen erforderlich sind.
DataContext data = new DataContext("http://ContosoServer"); DataContext juniorData = new DataContext("http://ContosoServer/JuniorTeamSite");
EntityList<Announcement> Announcements = data.GetList<Announcement>("Announcements");
EntityList<Announcement> JuniorAnnouncements = juniorData.GetList<Announcement>("Announcements");
var seniorAnns = from ann in Announcements
select ann;
var juniorAnns = from ann in JuniorAnnouncements
select ann;
IEnumerable<Announcement> mergedAnns = seniorAnns.union(juniorAnns);
foreach (Announcement ann in mergedAnns)
{
Console.WriteLine(ann.Title);
}
Diese Regel impliziert, dass von einer impliziten Verknüpfung zwischen zwei SharePoint Foundation-Listen ausgehende Abfragen nur unterstützt werden, wenn das Verknüpfungsfeld als Nachschlagefeld konfiguriert ist.
Zweiphasige Abfragen
Manche LINQ-Abfragen können nicht vollständig in CAML übersetzt werden. Solche Abfragen können jedoch im Prinzip ordnungsgemäß ausgeführt werden, da sie in zwei Phasen durchgeführt werden können. Zunächst übersetzt der LINQ to SharePoint-Anbieter möglichst viel von der Abfrage in CAML und führt sie aus. Dabei wird eine Obermenge der Daten erstellt, die von der Inhaltsdatenbank als IEnumerable<T>-Objekt an den Front-End-Webserver zurückgegeben werden. Im zweiten Schritt werden die restlichen Teile der Abfrage als LINQ to Objects-Abfrage für das IEnumerable<T>-Objekt neu erstellt. Die erste Phase muss jedoch mit einer einzigen Abfrage für die Inhaltsdatenbank ausgeführt werden können, da andernfalls für die gesamte Abfrage eine Ausnahme gemeldet wird.
Stellen Sie sich als Beispiel für eine einphasige Abfrage eine select-LINQ-Klausel wie z. B. "select new { c.Name, c.ZipCode }" vor. Diese kann als <ViewFields>-Tag mit zwei untergeordneten <FieldRef>-Elementen in CAML übersetzt werden. Die Klausel "select new { c.Price*2, c.Orders, c.Customer }" enthält aber eine mathematische Funktion, die in CAML nicht unterstützt wird. Die Abfrage wird demnach von LINQ to SharePoint übersetzt und ausgeführt, jedoch nur bis zur select-Klausel. Anschließend werden die von der CAML-Abfrage empfangenen Ergebnisse als IEnumerable<T>-Objekt an den Front-End-Webserver gesendet. Von einer neuen LINQ-Abfrage auf dem Front-End-Webserver wird dann die select-Klauselprojektion im Objekt mithilfe der Enumerable.Select()-Methode von LINQ to Objects ausgeführt.
Es gibt keine einfache Methode, um LINQ-Operatoren anzugeben, die nicht unterstützt werden oder die zwei Phasen erfordern. Beispielsweise wird wie weiter oben erwähnt der Union()-Operator nicht unterstützt, wenn es sich bei beiden zusammenzuführenden Datenquellen um Listen aus der Inhaltsdatenbank handelt. Wenn jedoch nur eine der Datenquellen eine SharePoint Foundation-Liste ist und die andere Datenquelle z. B. eine bereits im Arbeitsspeicher vorhandene Tabelle ist, kann Union() verwendet werden.
Für Abfragemethoden, die mathematische Operationen erfordern, werden in der Regel zwei Phasen benötigt. Es gibt jedoch Ausnahmen, wenn LINQ to SharePoint einen Wert aus dem SharePoint Foundation-Objektmodell abrufen kann. Beispielsweise erfordern die Methoden Count() und LongCount() keine Aufteilung der Abfrage in zwei Phasen.
Die folgenden Operatoren erfordern in der Regel zwei Phasen und werden normalerweise ordnungsgemäß ausgeführt, vorausgesetzt für die erste Phase ist nur eine einzige Abfrage der Inhaltsdatenbank erforderlich.
Wenn die Unterscheidung keine Rolle spielt
Wenn Sie die Ausgabe der übersetzbaren CAML-Teile der Abfrage mithilfe der Methoden ToList<TSource>(IEnumerable<TSource>), ToDictionary() oder ToArray<TSource>(IEnumerable<TSource>) dennoch in ein IEnumerable<T>-Objekt schreiben, verwendet der Teil der Abfrage nach dem Aufruf einer dieser Methoden die Abfrageoperatoren aus der Enumerable-Klasse anstelle der Queryable-Klasse. In diesem Fall spielt die Unterscheidung zwischen zweiphasigen und einphasigen Abfragen keine Rolle.
Vergleichen Sie z. B. die folgenden beiden Abfragen. Beide Abfragen würden zwei Phasen erfordern, da der mathematische Operator "-" verwendet wird. Von der zweiten Abfrage wird dies jedoch explizit ausgeführt, da LINQ to SharePoint nur in der Zeile from verwendet wird, womit die gesamte Liste orders in IList<T> eingelesen wird.
var ordersInArrears = from order in orders
where order.Price – order.Paid > 0
select order;
var ordersInArrears = from order in orders.ToList()
where order.Price – order.Paid > 0
select order;
Die manuelle Aufteilung der Abfragen in eine LINQ to SharePoint-Komponente und eine LINQ to Objects-Komponente kann auch die Verwendung von LINQ-Schlüsselwörtern ermöglichen, die andernfalls nicht unterstützt würden. Beispielsweise wäre der folgende Versuch der Zusammenführung von zwei Ankündigungssätzen erfolgreich, da die LINQ to SharePoint-Abfrage in zwei IEnumerable<T>-Objekten separat aufgezählt würden. Das verwendete union-Schlüsselwort ist die LINQ to Objects-Version von Union().
DataContext data = new DataContext("http://ContosoServer"); DataContext juniorData = new DataContext("http://ContosoServer/JuniorTeamSite");
EntityList<Announcement> Announcements = data.GetList<Announcement>("Announcements");
EntityList<Announcement> JuniorAnnouncements = juniorData.GetList<Announcement>("Announcements");
List<Announcement> seniorAnns = (from ann in Announcement
select ann).ToList();
List<Announcement> juniorAnns = (from ann in JuniorAnnouncements
select ann).ToList();
IEnumerable<Announcement> mergedAnns = seniorAnns.union(juniorAnns);
foreach (Announcement ann in mergedAnns)
{
Console.WriteLine(ann.Title);
}
Siehe auch
Referenz
Select