I have two tables:
block: int id, [other columns...]
blockInstance: int id, int blockId (references Block.Id), [other columns...]
My goal is to generate an enumeration of block objects with two properties: (1) Id (the Id of the Block) and (2) InstanceCount (the number of Instances for the Block). Currently, my XML file contains no Block Instances (that table exists but has zero rows).
Here's my (non-working) query:
var groupedBlocks =
from
b in _tableDictionary["block"].Elements()
join
bi in _tableDictionary["blockInstance"].Elements()
on b.Element(_ns + "id").Value equals bi.Element(_ns + "blockId").Value into j
from
lj in j.DefaultIfEmpty()
group
lj by b.Element(_ns + "id").Value into g
select new
{
Id = g.Key,
InstanceCount = g.Count(i => i.Element(_ns + "blockId") != null)
};
The problem is with the predicate (lambda expression) for g.Count(). If I remove the predicate and just use g.Count(), the query generates the proper number of rows, but the InstanceCount for each row is 1, which is wrong (it should be zero). With the predicate in there, the query return zero rows, and if I attempt to view the ResultsView in the debugger, it says "Exception: object reference not set to an instance of an object".
My greatest confusion is what exactly is "i" in my lambda expression. I know it's an XElement, but what does this XElement contain when the data is the result of a join (in this case, a left outer join)?
Okay, well I got one more idea while I was typing this out, and it actually worked :-), but I have no idea why :-(, so I'm still going to ask the question ;-).
If I change the offending code to...
InstanceCount = g.Count(i => i != null)
...it works. But why?! Again, what is getting passed into the lamba expression? And why is it null?
Thanks!