Question

I'm trying to pull out the Roles below into an IEnumerable<KeyValuePair<int, string>>

<PROJECT PROJECT_NO="161917"> 
  <CONTACT CLIENT_ID="030423253272735482765C" CONTACT_NO="1"> 
    <ROLE ROLE_ID="2" ROLE_DESC="ARCHITECT" /> 
    <ROLE ROLE_ID="5" ROLE_DESC="INTEGRATOR" /> 
  </CONTACT>
</PROJECT>



private static ProjectContact BuildProjectContactFromXml(XElement xml)
    {
        ProjectContact projectContact = new ProjectContact();
        projectContact.ProjectId = SafeConvert.ToInt32(xml.Attribute("PROJECT_NO").Value);
        projectContact.Roles = xml.Elements()
                                    .First()
                                    .Elements()
                                    .Select(role => new KeyValuePair<int, string>(
                                                            SafeConvert.ToInt32(role.Attribute("ROLE_ID").Value), 
                                                            role.Attribute("ROLE_DESC").Value));

        return projectContact;
    }

My question is about deferred execution of this Linq statement. It is my understanding that when I return this ProjectContact, the Linq statement has not yet executed. Is there a way to force the execution of this statement so that it happens in this method, rather than when someone tries to access the Roles? I think I could force the execution of the statement by calling .Count() on it, but it seems like there should be a better way.

Was it helpful?

Solution

projectContact.Roles is going to be a IEnumerable<KeyValuePair<int, string>> is that what you want, or do you want it as a List or DIctionary? For a List, just tack .ToList() at the end of the statement.

For a Dictionary, it's a bit trickier:

   projectContact.Roles = xml.Elements() 
                                .First() 
                                .Elements()
                                .ToDictionary(
                 role=> SafeConvert.ToInt32(role.Attribute("ROLE_ID").Value),
                 role=> role.Attribute("ROLE_DESC").Value)); 

UPDATE: In you comments you state that Roles id IEnumerable<KeyValuePair<int, string>>. Technically, that could be either a Dictionary or a List, although in the former case, you really can't use it's Dictionary-ness via that interface. For that matter, you can use much of it's List-ness in the latter case -- but it seems you specifically don't want that ability.

So, tack on .ToList();. It will be a List behind the scenes, but without going to extradinary lengths, users will still only be able to use it as an IEnumerable.

OTHER TIPS

If the datatype of .Roles is array, you could simply append .ToArray() after your .Select(), and that would ensure that the query is executed.

Either way, you can execute a ToList() or .ToArray(), and you'll get execution of the query.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top