問題描述
如何優化 Linq to Xml 查詢反對屬性? (How do I optimize a Linq to Xml query againist attributes?)
Given the following Xml fragment:
<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>
Which can be created with the following code:
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))));
Is this the best way to find the row where the r attribute is 2? This works, but I am repeating the Where clause in the select statement, and I am wondering if there is a better way and more efficent method.
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>();
In general what is the best way to determine if Linq to Xml query optimized?
‑‑‑‑‑
參考解法
方法 1:
The best way is:
var row = testElement
.XPathSelectElements("sheetData/row[@r='2']")
.FirstOrDefault();
A pure LINQ query that doesn't repeat the Where
call:
var row = testElement
.Descendants("sheetData")
.Descendants("row")
.Where(x => x.Attribute("r").Value == "2")
.FirstOrDefault();
方法 2:
//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());
方法 3:
Isn't the Select clause in your code redundant? Where returns an IEnumerable<XElement>
already. I think
var row = testElements.Descendents("row").Where(e => (int)e.Attribute("r") == rowNumber).SingleOrDefault();
should do what you want
(by David Basarab、Robert Rossney、eglasius、Lee)