0

Apologies if this is a duplicate or if I just need to RTFM, but I couldn't find a post that exactly answered my question. I feel I'm reinventing the wheel and there must be a better way. MVC4, Entity Framework 5. I'm using LINQ to project a list of entities from my domain into a list of view models, and encountering NULL reference exceptions, in situations where the navigation property points to a single related entity; for navigation properties which are collections a single level deep; then for those where there may be a navigation property that itself has a navigation property (i.e., maybe two levels deep).

It appears to work when I'm pointing to the actual database; I believe this is because my configuration has lazy loading turned on; but then when I write unit tests I'm getting the NULL reference exceptions. I've got a solution but there's a bit of a code smell. I'd like to find a cleaner solution that works in both situations.

Please consider the following code:

var theList = DomainContext.MyParentEntities.Select(g => new SomeViewModelForAList {

        SomeStringProperty = g.SingleRelatedEntity.Name,
        SomeIntProperty = 
            g.EntitiesFromSomeOtherTable.Count(x => !x.IsDeleted),
        SomeOtherIntProperty =
            g.YetAnotherRelatedEntity.YetMoreChildren.Count(x => !x.IsDeleted)

}).ToList();

Now, it's possible that any of the following entities related to MyParentEntities instances could be NULL: "SingleRelatedEntity", "EntitiesFromSomeOtherTable", "YetAnotherRelatedEntity", and/or "YetMoreChildren". Any of those could throw an exception.

I can write all sorts of NULL coalescing code, which works, but appears redundant and ugly. I've also looked at writing extension methods as described here (although Jimmy's post looks a bit old and maybe there's a better way now):

http://lostechies.com/jimmybogard/2009/12/08/linq-query-operators-and-null-lists/

The extension method idea works, and the technique can be adapted to single related entities using generics; here are my attempts to do that:

    public static IEnumerable<TSource> NullsToEmpty<TSource>(this IEnumerable<TSource> source)
    {
        return source ?? Enumerable.Empty<TSource>();
    }

    // same idea here

    public static T NullToEmpty<T>(this T theEntity) where T : EntityBase, new()
    {
        var retVal = new T();
        if (theEntity == null)
        {
            retVal.Name = "";
        }
        else
        {
            retVal = theEntity;    
        }

        return retVal;
    }

The code then becomes:

var theList = DomainContext.MyParentEntities.Select(g => new SomeViewModelForAList {

        SomeStringProperty = g.SingleRelatedEntity.NullToEmpty().Name,
        SomeIntProperty = 
            g.EntitiesFromSomeOtherTable.NullsToEmpty().Count(x => !x.IsDeleted),
        SomeOtherIntProperty =
            g.YetAnotherRelatedEntity.NullToEmpty().
            YetMoreChildren.NullsToEmpty().Count(x => !x.IsDeleted)

}).ToList();

Again this works but also feels like it's ugly and repetitive. Any suggestions appreciated. Thank you, -dB

David Barrows
  • 758
  • 7
  • 20

1 Answers1

0

I've made a few additional observations. There are a number of issues:

  • you can't easily unit test Entity Framework unless you do integration and/or end-to-end tests, as described by Ladislov here and elsewhere:

Is UnitOfWork and GenericRepository Pattern redundant In EF 4.1 code first?

  • it's a matter of getting the Linq query right such that there aren't round trips to the database, avoiding N + 1 issues, grabbing the entire object graph etc (i.e. integration and unit tests are needed to make sure you've got it right

  • (in my case at least), the NULLs are not an issue in production as EF translates to SQL which checks IF EXISTS; thus I don't need "DefaultIfEmpty()" as described for example here:

http://www.progware.org/Blog/post/Left-Outer-Join-in-LINQ-to-Entities-%28for-Entity-Framework-4%29.aspx

  • in my unit tests I simulate EF's behaviour by returning (for empty sets) a new empty Collection (so avoid the NullToEmpty technique, which LINQ to Entities can't interpret anyway)
Community
  • 1
  • 1
David Barrows
  • 758
  • 7
  • 20