Make sure to check for null in the select of a LINQ to objects query when using a left outer join.

The following example illustrates how to get a method value out of class that is the target of the outer join. The code can be run in LINQPad as a C# program.


class Foo
{
    public int FooKey { get; set; }
    public string FooVal { get; set; }
}

class Bar
{
	public int BarKey { get; set; }
    public string BarVal { get; set; }
}

void Main()
{
	List<Foo> aListOFoo = new List<Foo> {
        new Foo { FooKey = 1, FooVal = "FooVal1" },
        new Foo { FooKey = 2, FooVal = "FooVal2" },
        new Foo { FooKey = 3, FooVal = "FooVal3" } };
    
    List<Bar> aListOBar = new List<Bar> {
        new Bar { BarKey = 1, BarVal = "BarVal1" },
        new Bar { BarKey = 2, BarVal = "BarVal2" } };
        
    var q =
        from f in aListOFoo
            join b in aListOBar on f.FooKey equals b.BarKey into fbJoin
        from bLeftJoin in fbJoin.DefaultIfEmpty()
        select new { 
            f.FooVal, 
            BarVal = bLeftJoin != null ? bLeftJoin.BarVal : null };
    
    q.Dump();
}

The output for the above code in LINQPad:

LINQPad output for LINQ to Objects left outer join

If the select used bLeftJoin.BarVal without the ternary check for null, then the query would return Object reference not set to an instance of an object.

I'm not a huge fan of LINQ outer join syntax, but LINQ brings me much happiness nonetheless :-)

Technical .NET LINQ November 26, 2011

It is not uncommon to find myself needing to page through a collection of .NET objects in memory. LINQ to objects provides a great way to accomplish paging using the Skip and Take extension methods.

The following example code illustrates the pattern in C#.


List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int chunkSize = 3, index = 0;
IEnumerable<int> chunk = list.Take(chunkSize);

while( chunk.Count() > 0 )
{
	// Do something with the chunk of data.
	chunk.Dump(); // This shows the data in LINQPad.
	
	index += chunkSize;
	chunk = list.Skip(index).Take(chunkSize);
}

The results of the above code in LINQPad:

LINQ to objects in memory paging results

A common scenario that arises is the need to run a database query with an in clause across a large amount of data in memory. A where clause with a condition comparing to a list in an ORM tool normally results in an IN clause with bound parameters. Since SQL Server can have a limited number of entries in an IN clause, somewhere around 2,000, processing can easily be done by paging through the data in memory.

Happiness :-)

Technical .NET LINQ November 25, 2011