2009-03-19 3 views
1

Учитывая следующий фрагмент Xml:Как оптимизировать атрибуты повторного запроса запроса Linq to Xml?

<root> 
    <sheetData> 
    <row r="1" /> 
    <row r="2" /> 
    <row r="3" /> 
    <row r="4" /> 
    <row r="5" /> 
    <row r="6" /> 
    <row r="7" /> 
    </sheetData> 
</root> 

который может быть создан с помощью следующего кода:

XElement testElement = new XElement("root", 
    new XElement("sheetData", 
     new XElement("row", 
      new XAttribute("r", 1)), 
     new XElement("row", 
      new XAttribute("r", 2)), 
     new XElement("row", 
      new XAttribute("r", 3)), 
     new XElement("row", 
      new XAttribute("r", 4)), 
     new XElement("row", 
      new XAttribute("r", 5)), 
     new XElement("row", 
      new XAttribute("r", 6)), 
     new XElement("row", 
      new XAttribute("r", 7)))); 

Является ли это лучший способ найти строку, где атрибут г 2? Это работает, но я повторяю предложение Where в инструкции select , и мне интересно, есть ли лучший способ и более эффективный метод.

int rowNumber = 2; 

XElement rowElement = testElement 
    .Descendants("sheetData") 
    .Where<XElement>(item => item.Descendants("row") 
            .Where<XElement>(i => i.Attribute("r").Value == rowNumber.ToString()) 
            .FirstOrDefault<XElement>() != null) 
    .Select<XElement, XElement>(item => item.Descendants("row") 
            .Where<XElement>(i => i.Attribute("r").Value == rowNumber.ToString()) 
            .FirstOrDefault<XElement>()) 
    .FirstOrDefault<XElement>(); 

В общем, что лучше всего определить, оптимизирован ли Linq для Xml-запроса?

ответ

3

Лучший способ:

var row = testElement 
    .XPathSelectElements("sheetData/row[@r='2']") 
    .FirstOrDefault(); 

Чистый LINQ запрос, который не повторяет Where вызова:

var row = testElement 
    .Descendants("sheetData") 
    .Descendants("row") 
    .Where(x => x.Attribute("r").Value == "2") 
    .FirstOrDefault(); 
+0

где определены XPathSelectElements? если это метод расширения, пожалуйста, разместите пространство имен, я хотел бы иметь это в XElement :) – eglasius

+0

Я бы использовал .Where (x => (string) x.Attribute ("r") == "2") вместо этого , Если атрибут 'r' не существует, он не будет вызывать исключение NullReferenceException. –

+0

нашел это: http://msdn.microsoft.com/en-us/library/bb342176.aspx ... +1 очень приятно :) - Я обязательно воспользуюсь этим – eglasius

1
//if sheetData appears multiple times 
    XElement rowElement = testElement 
     .Descendants("sheetData") 
     .SelectMany(s=>s.Descendats("row)) 
     .Where(i=>i.Attribute("r").Value == rowNumber.ToString()); 
//if sheetData appears once 
    XElement rowElement = testElement 
     .Element("sheetData") 
     .Descendants("row)) 
     .Where(i=>i.Attribute("r").Value == rowNumber.ToString()); 
0

не является Выберите пункт в вашем коде лишний? Куда возвращается IEnumerable<XElement>. Я думаю, что

var row = testElements.Descendents("row").Where(e => (int)e.Attribute("r") == rowNumber).SingleOrDefault(); 

должны делать то, что вы хотите

Смежные вопросы