views:

378

answers:

1

I have an odd linq subquery issue.

Given the following data structure:

Parents            Children
-------            --------
Id                 Id
                   ParentId
                   Location
                   HasFoo

(obviously this is not the real structure, but it's close enough for this example)

I'm able to run this query and get a desired result:

bool b = (from p in Parents
          from c in Children
          where p.Id == 1 && c.ParentId == p.Id && c.Location == "Home"
          select c.HasFoo).SingleOrDefault();

So if there is a child that has the Location "Home" for a Parent of Id 1, I will get that Child's "HasFoo" value, otherwise, I'll get false, which is the "default" value for a bool.

However, if I try and write the query so I have a list of Parent objects, like so:

var parentList = from p in Parents
                 select new ParentObject
                 {
                   ParentId = p.ParentId,
                   HasHomeChildren = p.Children.Count(c => c.Location == "Home") > 0,
                   HasHomeChildrenWithFoo = (from c in p.Children where c.Location == "Home" select c.HasFoo).SingleOrDefault()
                 }

I get the following error when iterating over the list:

The null value cannot be assigned to a member with type System.Boolean which is a non-nullable value type.

I don't see where this "null" value is coming from, however.

+1  A: 

I wonder if the compiler is inferring HasHomeChildrenWithFoo to be bool, but then actually casting to a nullable bool (thus messing up your SingleOrDefault call). At any rate, I'd be willing to bet you could fix it with a cast to a nullable type in that final select which you can then manually default to false when null. It'd probably make the error go away, but it's kind of a brute-force kludge.

var parentList = from p in Parents
                 select new ParentObject
                 {
                   ParentId = p.ParentId,
                   HasHomeChildren = p.Children.Count(c => c.Location == "Home") > 0,
                   HasHomeChildrenWithFoo = (from c in p.Children where c.Location == "Home" select (bool?)c.HasFoo) ?? false)
                 }
Jacob Proffitt
Seems very odd to have to do this, but it works! Thanks! :)
Jonas
Yeah I know it's odd :). Glad it worked. I stumbled onto the trick on a similar question a bit ago (http://stackoverflow.com/questions/341264/). The article I linked there might shed more light if you're interested: http://www.interact-sw.co.uk/iangblog/2007/09/10/linq-aggregates
Jacob Proffitt
Great article...thanks again :)
Jonas