简体   繁体   中英

How do I fix my linq query

Here's the sample XML

<?xml version="1.0" encoding="utf-8" ?>
<Instructions>
  <Instruction>
    <Brand>Brand1</Brand>
    <Text>
      this is text for Brand1
    </Text>
  </Instruction>
  <Instruction>
    <Brand>Brand2</Brand>
    <Text>
      Brand2 text is slightly different
    </Text>
  </Instruction>
  <Instruction>
    <Brand>Brand3</Brand>
    <Text>
      Brand3 has boring text
    </Text>
  </Instruction>
  <Instruction>
    <Brand>Brand4</Brand>
    <Text>
      Brand4 had long text until the editor got hold of this file
    </Text>
  </Instruction>
</Instructions>

My code is this:

string WhoAmI = "Brand1";
string t =
              (from Instruction in xmlDoc.Descendants("Instruction")
               where (string)Instruction.Element("Brand").Value == WhoAmI
               select t = Instruction.Element("Text").Value
               ).ToString();

//end code

t is always

System.Linq.Enumerable+WhereSelectEnumerableIterator`2 [System.Xml.Linq.XElement,System.String]

not

this is text for Brand1

What am I doing wrong?

A LINQ statement returns a sequence of values, not a single value. So calling .ToString() on a sequence object will, ordinarily, not give you anything particularly useful.

In this case, your statement is returning a sequence with one value in it, but still a sequence. So you need to write a LINQ statement that only returns one value:

string t = (from ... select ...).First();

There's other implications to consider here, such that First() will throw an exception if the sequence is empty. FirstOrDefault() will return null instead.

尝试用FirstOrDefault()替换ToString() FirstOrDefault()

This query will return a sequence of strings not a single string. So the .ToString() method call will be the IEnumerable ToString method.

If you are confident that your query will always only return 1 string you can use the Single() or SingleOrDefault() methods to just return the string.

string WhoAmI = "Brand1"; 
string t = 
              (from Instruction in xmlDoc.Descendants("Instruction") 
               where (string)Instruction.Element("Brand").Value == WhoAmI 
               select t = Instruction.Element("Text").Value 
               ).SingleOrDefault();

This will give you a collection of the Text nodes' contained text values. However, if either a Text node or a Brand node is missing this query will fail. What the code you posted was doing was not accepting a collection as a result; you were casting the collection object returned to a string which by default gives you just the name of the object.

You will need to loop through the list returned by the query to do something useful with the multiple values returned...

        var results = (from e in doc.Descendants("Instruction")
                       where e.Descendants("Brand").First().Value == WhoAmI
                       select e.Descendants("Text").First().Value).ToList();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM