3

I would like to return a DTO from my data layer which would also contain child collections...such as this:

Audio
 - Title
 - Description
 - Filename
 - Tags
     -  TagName
 - Comments
     -  PersonName
     -  CommentText

Here is a basic query so far, but i'm not sure how to transform the child collections from my entity to the DTO.

var query = Session.CreateCriteria<Audio>("audio")
            .SetProjection(
                Projections.ProjectionList()
                    .Add(Projections.Property<Audio>(x => x.Title))
                    .Add(Projections.Property<Audio>(x => x.Description))
                    .Add(Projections.Property<Audio>(x => x.Filename))
            ).SetResultTransformer(new AliasToBeanResultTransformer(typeof(AudioDto)))
            .List<AudioDto>();

Is this even possible, or is there another reccomended way of doing this?

UPDATE: Just want to add a little more information about my scenario...I want to return a list of Audio items to the currently logged in user along with some associated entities such as tags, comments etc...these are fairly straight forward using MultiQuery / Future.

However, when displaying the audio items to the user, i also want to display 3 other options to the user:

  • Weather they have added this audio item to their list of favourites
  • Weather they have given this audio the 'thumbs up'
  • Weather the logged in user is 'Following' the owner of this audio
Favourites : Audio -> HasMany -> AudioUserFavourites

Thumbs Up : Audio -> HasManyToMany -> UserAccount

Following Owner : Audio -> References -> UserAccount ->

ManyToMany -> UserAccount

Hope this makes sense...if not i'll try and explain again...how can I eager load these extra details for each Audio entity returned...I need all this information in pages of 20 also.

I looked at Batch fetching, but this appears to fetch ALL thumbs ups for each Audio entity, rather than checking if only the logged in user has thumbed it.

Sorry for rambling :-)

Paul

Paul Hinett
  • 1,951
  • 2
  • 26
  • 40

1 Answers1

2

If you want to fetch your Audio objects with both the Tags collection and Comments collections populated, have a look at Aydende Rahien's blog: http://ayende.com/blog/4367/eagerly-loading-entity-associations-efficiently-with-nhibernate.

You don't need to use DTOs for this; you can get back a list of Audio with its collections even if the collections are lazily loaded by default. You would create two future queries; the first will fetch Audio joined to Tags, and the second will fetch Audio joined to Comments. It works because by the time the second query result is being processed, the session cache already has the Audio objects in it; NHibernate grabs the Audio from the cache instead of rehydrating it, and then fills in the second collection.

You don't need to use future queries for this; it still works if you just execute the two queries sequentially, but using futures will result in just one round trip to the database, making it faster.

Carl Raymond
  • 4,429
  • 2
  • 25
  • 39
  • well i was doing it this way before, although my problem is a little more complex than this...i have updated my question with more detail. – Paul Hinett Jun 15 '11 at 21:19
  • Those additional details suggest a DTO after all. Those collections could be huge, so you don't want to fetch the full contents of those; you just want the booleans. This answer http://stackoverflow.com/questions/5923007/how-to-select-with-nhibernate-queryover/5972357#5972357 has an example of populating a DTO from a query using WithAlias in QueryOver syntax. – Carl Raymond Jun 16 '11 at 16:04
  • thought so, I worked away on the DTO and come up with a good enough solution in the end. I pulled back all the single properties for my DTO in one query, and done a seperate query for each collection (MultiQuery) and added them to the DTO manually after. – Paul Hinett Jun 16 '11 at 22:58