0

I'm trying to add projection to an NHibernate LINQ query (via .select()), but since I have a bit of logic I want to use a helper class rather than returning a projected model directly.

My code looks like this (shortened):

var query = Session.Query<MessageInstance>();
... (a few .Fetch and .ThenFetch calls)
var result = query.Where(specification.IsSatisfiedBy())
                  .OrderBy(m => m.CreationDate)
                  .Select(m => _messageModelHelper.BuildMessageModel(m));

_messageModelHelper is an object which transforms my MessageInstance object into a MessageModel and it contains logic to handle different scenarios, since it all depends on related entities.

This fails with error:

Field Dal.Repositories.MessageRepository._messageModelHelper' is not defined for type 'NHibernate.Linq.NhQueryable`1 [Domain.Entities.Message]'

If I avoid using a field (which is necessary for DI), and do this:

.Select(m => new MessageModelHelper().BuildMessageModel(m))

I simply get a System.NotSupportedException.

It appears my approach won't work. What can I do, while avoiding the need to return new MessageModel directly? Also I really need to keep projection, I can't operate on an enumerable.

MarioDS
  • 12,895
  • 15
  • 65
  • 121

1 Answers1

0

You have to call the BuildMessageModel() "locally":

var result = query.Where(specification.IsSatisfiedBy())
                  .OrderBy(m => m.CreationDate)
                  .AsEnumerable() // From this point onward the query
                                  // will be executed C#-side
                  .Select(m => _messageModelHelper.BuildMessageModel(m));

Note that, as written, this won't do an SQL projection, so the full object will be selected from the DB.

xanatos
  • 109,618
  • 12
  • 197
  • 280
  • Okay, I should have made it more clear but I actually want to keep projection... The reason I can't use `AsEnumerable` anyway is that we have a custom extension method to retrieve a paged collection. – MarioDS Jun 19 '15 at 11:25
  • @MDeSchaepmeester Then first you page, then from the result of paging you do the `_messageModelHelper.BuildMessageModel(m)`, like var result2 = result.Select(m => _messageModelHelper.BuildMessageModel(m)).ToArray(); – xanatos Jun 19 '15 at 11:25
  • @xantos: yes, but there is still no projection then, I want to keep the performance benefits of that. – MarioDS Jun 19 '15 at 11:26
  • @MDeSchaepmeester What I normally do is project the properties I need and then, with a method, enrich the result object with calculated properties. Clearly the enrichment happens after the query is executed. If I'm lazy I use a single class that is partially filled by the query and partially filled by the enrichment method. If I'm not lazy I create two classes (`PartialResult` and `FinishedResult`), but then I have to copy properties from `PartialResult` to `FinishedResult`. – xanatos Jun 19 '15 at 11:31