Sunday, August 25, 2013

Safe Navigation via Linq

AdventureWorks product's model is nullable. Null exception will be raised when we navigate the Name of the ProductModel from the Product.

var products = session.Query<Product>().Fetch(x => x.ProductModel);

foreach (var prod in products)
{
        Console.WriteLine("Product: {0}", prod.Name);
   
        // this will raise a null exception when Production.Product.ProductModelID is null
        Console.WriteLine("Model: {0}", prod.ProductModel.Name); 
}


Aside from using null-safe navigation extension method...

var products = session.Query<Product>().Fetch(x => x.ProductModel);

foreach (var prod in products)
{
        Console.WriteLine("Product: {0}", prod.Name);
        Console.WriteLine("Model: {0}", prod.ProductModel.NullSafe(x => x.Name));
}

...we can just flatten the domain models from Linq's projection, the database won't balk on navigating nullable product model from the product, then the ORM can happily map the null value to the property.

var products = session.Query<Product>()
                    // .Fetch(x => x.ProductModel) // This is not needed anymore, as we efficiently select only the needed columns on our projection
                    .Select(x => 
                            new { 
                                 ProductName = x.Name, 
                                 ProductModelName = x.ProductModel.Name // database don't have problem projecting null
                            });

foreach (var prod in products)
{
        Console.WriteLine("Product: {0}", prod.ProductName);
        Console.WriteLine("Model: {0}", prod.ProductModelName);
}

We can't do that trick on in-memory objects, for those scenario just use safe navigation extension method.



Happy Coding! ツ

No comments:

Post a Comment