Linq

Using Linq To XML to output XML with null members

Despite having spent a large part of the past 12 years writing and optimising SQL queries on various flavours of SQL Server (or perhaps because of that) I still find it difficult to ‘think in Linq’. I see examples of things you can do and all I can think is ‘How do you even start to express such a query?’. I must be getting old.

Case in point – an apparently simple query to take a collection of objects and generate an XML representation. Most of this is easy, but there’s one wrinkle – one of the class members can be null and if it is, I don’t want anything showing up in the destination XML. Such a thing is easy to do in boring old procedural C# with ifs and foreachs, but in Linq it’s not immediately obvious how to express it.

It felt like it might need a subquery but you can’t run a linq query over a simple class – it’s not an enumerable type so linq won’t work. Here’s what I tried:


            var xml = new XElement("Points", from poi in walkData
                      select new XElement("PointOfInterest",
                        new XElement("GridReference",
                            new XElement("Easting", poi.gridReference.Easting),
                            new XElement("Northing", poi.gridReference.Northing)),
                         from tween in poi.TweenData where tween != null 
                            select new XElement("TweenData",
                                new XElement("Angle",poi.TweenData.Angle),
                                new XElement("TweenType",poi.TweenData.Tween),
                                new XElement("Zoom",poi.TweenData.Zoom))));

But I get the following error:

“Could not find an implementation of the query pattern for source type ‘TweenData’.  ‘Where’ not found.”

This is telling me that my TweenData class isn’t enumerable.

So I tried a different tack – what I basically want to do is output something if TweenData isn’t null, so how do I do an if in an expression. I settled on an idiom I generally avoid – the ternary conditional operator – which allows me to either output the XML for a non-null TweenData or pass null. Handily, the XElement constructor is happy to accept null as one of its parameters and output nothing. Here’s the working query:


            var xml = new XElement("Points", from poi in walkData
                    select new XElement("PointOfInterest",
                        new XElement("GridReference",
                              new XElement("Easting", poi.gridReference.Easting),
                              new XElement("Northing", poi.gridReference.Northing)),
                         poi.TweenData == null ? null : new XElement("TweenData",
                              new XElement("Angle", poi.TweenData.Angle),
                              new XElement("TweenType", poi.TweenData.Tween),
                              new XElement("Zoom", poi.TweenData.Zoom))));

This query does exactly what I want – if TweenData is non-null it outputs the data in a <TweenData> element, otherwise nothing appears at that point in the output xml.

I still feel uncomfortable about using the query operator. The C++ and C# style guides my team uses explicitly discourages its use, because it often leads to harder to read code. But just now, I can’t think of a more Linqy way to do the same thing. So I’m gritting my teeth and going with what works.