Sdílet prostřednictvím


Staticky kompilované dotazy (LINQ to XML)

Jednou z nejdůležitějších výhod výkonu jazyka LINQ to XML je, XmlDocumentže dotazy v JAZYCE LINQ to XML jsou staticky kompilovány, zatímco dotazy XPath musí být interpretovány za běhu. Tato funkce je integrovaná do LINQ to XML, takže nemusíte provádět další kroky, abyste ji mohli využít, ale je užitečné pochopit rozdíl při výběru mezi těmito dvěma technologiemi. Tento článek vysvětluje rozdíl.

Staticky kompilované dotazy vs. XPath

Následující příklad ukazuje, jak získat potomky elementy se zadaným názvem a atributem se zadanou hodnotou. Ekvivalentní výraz XPath je //Address[@Type='Shipping'].

XDocument po = XDocument.Load("PurchaseOrders.xml");

IEnumerable<XElement> list1 =
    from el in po.Descendants("Address")
    where (string)el.Attribute("Type") == "Shipping"
    select el;

foreach (XElement el in list1)
    Console.WriteLine(el);
Dim po = XDocument.Load("PurchaseOrders.xml")

Dim list1 = From el In po.Descendants("Address")
            Where el.@Type = "Shipping"

For Each el In list1
    Console.WriteLine(el)
Next

Výraz dotazu v tomto příkladu přepíše kompilátor na syntaxi dotazu založenou na metodách. Následující příklad, který je napsaný v syntaxi dotazů založených na metodách, vytvoří stejné výsledky jako předchozí:

XDocument po = XDocument.Load("PurchaseOrders.xml");

IEnumerable<XElement> list1 =
    po
    .Descendants("Address")
    .Where(el => (string)el.Attribute("Type") == "Shipping");

foreach (XElement el in list1)
    Console.WriteLine(el);
Dim po = XDocument.Load("PurchaseOrders.xml")

Dim list1 As IEnumerable(Of XElement) = po.Descendants("Address").Where(Function(el) el.@Type = "Shipping")

For Each el In list1
   Console.WriteLine(el)
Next

Metoda Where je rozšiřující metoda. Další informace naleznete v tématu Metody rozšíření (Průvodce programováním v C#). Vzhledem k tomu Where , že je metoda rozšíření, výše uvedený dotaz je zkompilován, jako by byl napsán takto:

XDocument po = XDocument.Load("PurchaseOrders.xml");

IEnumerable<XElement> list1 =
    System.Linq.Enumerable.Where(
        po.Descendants("Address"),
        el => (string)el.Attribute("Type") == "Shipping");

foreach (XElement el in list1)
    Console.WriteLine(el);
Dim po = XDocument.Load("PurchaseOrders.xml")

Dim list1 = Enumerable.Where(po.Descendants("Address"), Function(el) el.@Type = "Shipping")

For Each el In list1
    Console.WriteLine(el)
Next

Tento příklad vytvoří přesně stejné výsledky jako předchozí dva příklady. To ilustruje skutečnost, že dotazy jsou efektivně kompilovány do staticky propojených volání metod. To v kombinaci s sémantikou odloženého provádění iterátorů zlepšuje výkon. Další informace o sémantice odloženého provádění iterátorů naleznete v tématu Odložené provádění a opožděné vyhodnocení.

Poznámka:

Tyto příklady představují kód, který může kompilátor napsat. Skutečná implementace se může mírně lišit od těchto příkladů, ale výkon bude stejný jako u těchto příkladů nebo podobný.

Spouštění výrazů XPath s xmldocumentem

Následující příklad používá XmlDocument k dosažení stejných výsledků jako v předchozích příkladech:

XmlReader reader = XmlReader.Create("PurchaseOrders.xml");
XmlDocument doc = new XmlDocument();
doc.Load(reader);
XmlNodeList nl = doc.SelectNodes(".//Address[@Type='Shipping']");
foreach (XmlNode n in nl)
    Console.WriteLine(n.OuterXml);
reader.Close();
Dim reader = Xml.XmlReader.Create("PurchaseOrders.xml")
Dim doc As New Xml.XmlDocument()
doc.Load(reader)
Dim nl As Xml.XmlNodeList = doc.SelectNodes(".//Address[@Type='Shipping']")
For Each n As Xml.XmlNode In nl
    Console.WriteLine(n.OuterXml)
Next
reader.Close()

Tento dotaz vrátí stejný výstup jako příklady, které používají LINQ to XML; Jediným rozdílem je, že LINQ to XML odsadí tištěný XML, zatímco XmlDocument ne.

Obecně ale XmlDocument přístup nefunguje stejně jako LINQ to XML, protože SelectNodes metoda musí provést následující kroky při každém zavolání:

  • Parsujte řetězec obsahující výraz XPath a rozdělte řetězec na tokeny.
  • Ověřte tokeny a ujistěte se, že je výraz XPath platný.
  • Přeloží výraz do stromu interních výrazů.
  • Iterujte mezi uzly a odpovídajícím způsobem vyberte uzly pro sadu výsledků na základě vyhodnocení výrazu.

To je výrazně větší než práce provedená odpovídajícím dotazem LINQ to XML. Konkrétní rozdíl v výkonu se u různých typů dotazů liší, ale obecně platí, že dotazy LINQ to XML fungují méně, a proto fungují lépe než vyhodnocení výrazů XPath pomocí XmlDocument.