Accepted answer

As said in the comment you need the Include method:

SalesOrderHeaders.Include(s => s.SalesOrderDetails
                                .Select(d => d.SpecialOfferProduct))
                 .Where(s => s.SalesOrderID == 43659)

this will join the required data (in SQL) and populate the navigation properties.

Note, however, that you can't use syntax like

.Include(s => s.SalesOrderDetails.Where(sod => sod.OrderQty > 3)
               .Select(d => d.SpecialOfferProduct))

Which seemingly would partly populate SalesOrderDetails. There are change requests to the EF team to implement this, but so far, this hasn't been done.

Another side note is that it's useless to return SpecialProducts as IQueryable because subsequent queries on the collection won't get translated to SQL anyway. You can only access the property in in-memory statements in the first place, not in linq-to-enitites queries (EF cant translate the property into SQL).

Related Articles