Friday, December 23, 2011

The hard-to-see, camouflaged seam between IQueryable and IEnumerable and what it means for LinqSpecs

This line of code worked great:

foreach (Division division in DivisionRepository.FindAll(DivisionSecurityFilteringHelper.SpecificationForAllSecurityPermissionedDivisions(ListView.UserContext))) foreach (Account account in division.Accounts) OrderFilter.Accounts.Add(account.Id, account.Name);

 
 

Resharper suggested I refactor it to this however:

foreach (Account account in DivisionRepository.FindAll(DivisionSecurityFilteringHelper.SpecificationForAllSecurityPermissionedDivisions(ListView.UserContext)).SelectMany(division => division.Accounts)) OrderFilter.Accounts.Add(account.Id, account.Name);

 
 

Then it didn't work so well, returning:

Could not parse expression 'value(NHibernate.Linq.NhQueryable`1[AMD.Avalanche.Core.Entities.Division]).Where(d => (d.OwnersGroup.Profiles.Where(p => (p.Id == f740904e-3e43-4644-8194-9f8700fb904b)).Any() OrElse Invoke(d => d.OwnersGroup.Groups.Any(g => g.Profiles.Any(p => (p.Id == f740904e-3e43-4644-8194-9f8700fb904b))), d))).SelectMany(division => division.Accounts)': This overload of the method 'System.Linq.Queryable.SelectMany' is currently not supported, but you can register your own parser if needed.

 
 

When an IQueryable is executed it will pop-off (forgive the email term, it is marginally inappropriate) its contents to an IEnumerable or at least try to. In the second line of code above, I am shoving the concerns of a child object onto the IQueryable and thus sabotaging its ability to be popped-off. I don't have to shove these concerns onto the IQueryable, and yet there might be a little bit of optimization if I did do so, so it was worth a try. LinqSpecs are tricky.

No comments:

Post a Comment