Statiskt kompilerade frågor (LINQ till XML)

En av de viktigaste prestandafördelarna med LINQ till XML jämfört med XmlDocumentär att frågor i LINQ till XML kompileras statiskt, medan XPath-frågor måste tolkas vid körning. Den här funktionen är inbyggd i LINQ till XML, så du behöver inte utföra extra åtgärder för att dra nytta av den, men det är bra att förstå skillnaden när du väljer mellan de två teknikerna. Den här artikeln förklarar skillnaden.

Statiskt kompilerade frågor jämfört med XPath

I följande exempel visas hur du hämtar underordnade element med ett angivet namn och med ett attribut med ett angivet värde. Motsvarande XPath-uttryck är //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

Frågeuttrycket i det här exemplet skrivs om av kompilatorn till metodbaserad frågesyntax. Följande exempel, som är skrivet i metodbaserad frågesyntax, ger samma resultat som föregående:

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

Metoden Where är en tilläggsmetod. Mer information finns i Tilläggsmetoder (C#-programmeringsguide). Eftersom Where är en tilläggsmetod kompileras frågan ovan som om den skrevs på följande sätt:

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

Det här exemplet ger exakt samma resultat som de föregående två exemplen. Detta illustrerar det faktum att frågor effektivt kompileras till statiskt länkade metodanrop. Detta, i kombination med den uppskjutna körningssemantiken för iteratorer, förbättrar prestandan. Mer information om den uppskjutna körningens semantik för iteratorer finns i avsnittet Uppskjuten körning och lat utvärdering.

Anmärkning

De här exemplen är representativa för den kod som kompilatorn kan skriva. Den faktiska implementeringen kan skilja sig något från de här exemplen, men prestandan blir densamma som eller liknar dessa exempel.

Köra XPath-uttryck med XmlDocument

I följande exempel används XmlDocument för att uppnå samma resultat som i föregående exempel:

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()

Den här frågan returnerar samma utdata som de exempel som använder LINQ till XML. den enda skillnaden är att LINQ till XML drar in den utskrivna XML-koden, medan XmlDocument den inte gör det.

XmlDocument-metoden fungerar dock vanligtvis inte lika bra som LINQ för XML, eftersom SelectNodes-metoden måste göra följande varje gång den anropas:

  • Parsa strängen som innehåller XPath-uttrycket och dela upp strängen i token.
  • Verifiera token för att kontrollera att XPath-uttrycket är giltigt.
  • Översätt uttrycket till ett internt uttrycksträd.
  • Iterera genom noderna och välj noderna för resultatuppsättningen baserat på utvärderingen av uttrycket.

Detta är betydligt mer än det arbete som utförs av motsvarande LINQ till XML-fråga. Den specifika prestandaskillnaden varierar för olika typer av frågor, men i allmänhet fungerar LINQ till XML-frågor mindre och presterar därför bättre än att utvärdera XPath-uttryck med hjälp av XmlDocument.