I'm VERY new to using LINQ. I have the following XML:
<?xml version="1.0" encoding="utf-8" ?>
<root>
<RetentionValue code="NR" fullName="Normal Retention">Used for normal retention periods commonly expressed as only numbers (i.e. "25" for 25 years).</RetentionValue>
<RetentionValue code="SR" fullName="Short Retention">Used for short retention periods expressed in terms of months (i.e. "6 months").</RetentionValue>
<RetentionValue code="AR" fullName="Annual Review">Review annually and retain what is needed, dispose of what is not needed.</RetentionValue>
<RetentionValue code="PE" fullName="Permanent">Document is to be retained permanently.</RetentionValue>
<RetentionValue code="EX" fullName="Expiration">Disposal date is calculated from expiration of a contract, loan, or other such instrument.</RetentionValue>
<RetentionValue code="LI" fullName="Lifetime">Disposal date is calculated from the end-of-life date for a piece of equipment or other asset (e.g. software application).</RetentionValue>
<RetentionValue code="TE" fullName="Employee Termination">Disposal date is calculated from the date of termination or retirement of an employee.</RetentionValue>
<RetentionValue code="FR" fullName="Final Resolution">Disposal date is calculated from the date of final resolution for an issue.</RetentionValue>
</root>
In my code, I create an object that has a property RetentionEvent that has a value of one of the two-letter codes above. I want to find the Element with the matching Attribute, then return the fullName to one text field and the value (wordy description) to another text field. So far I have the following:
// Construct a RecordDisposal object by passing it a valid retention code.
// An exception will be thrown if the code is not valid.
_rd = new RecordDisposal(RetentionCode.Text);
// Load up XML file with description of codes.
XDocument rangeValues = XDocument.Load("DisposalRangeValues.xml");
XElement codeValue = rangeValues.Root.Elements().Single(x => (string)x.Attribute("code") == _rd.DisposalList[0].RetentionEvent);
CodeName.Text = codeValue.Attribute("fullName").Value.ToString();
CodeDescription.Text = codeValue.Value.ToString();
The query is a straight mod of this code (I think), however I'm getting a couple of errors I don't understand: "A query body must end with a select clause or a group clause" (I thought that's what the ToList() was for), and "The type of the expression in the select clause is incorrect. Type inference failed in the call to 'Select'." Unfortunately, I don't understand Linq well enough to troubleshoot this, and "Help on this error" provides nothing useful.
What have I done incorrectly? Also, I'm suspicious that the ToList() function is going to return something that doesn't render well in the ToString() function, but I was waiting to figure out the other stuff before fooling with that. If anyone has a suggestion, please offer it.
EDIT: Modified code to use Single based on recommendation below. Discovered that rangeValues is loading all of <root> as a single node.
EDIT2: Figured it out. Modified code to use rangeValues.Root.Elements() instead. Updated code above to reflect.