1

I just noticed that on one page of my site, where I pass a ViewModel to my View page, NHProf is giving the following warning:

This statement executed from the view, which can result in bad performance and/or brittle behaviour.

It then links to this page: http://nhprof.com/Learn/Alerts/QueriesFromViews

My ViewModel consists of just 2 properties:

public IEnumerable<Photo> Photos { get; set; }
public Photo SelectedPhoto { get; set; }

I assign the photos to this ViewModel within my Controller as follows:

PhotoViewModel myViewModel = new PhotoViewModel();
myViewModel.Photos = entity.Photos;

My View obviously inherits this type, and aside from outputting a header (which makes use of the SelectedPhoto object), it just loops through each of the Photos rendering some content for each of them.

NHProf shows the 'problem' query as being where it retrieves the collection of Photos that I'm looping through in my view, though I'm not explicitly telling it to go off and get those records from within my view - I've passed those records within the Photos property of my ViewModel.

I have other pages where I don't need to pass a ViewModel and I simply pass IEnumerable<Photo> to the View, and then render the markup exactly the same as I do in the problem view, and NHProf gives no warnings (as there shouldn't be) in that scenario.

I'm thinking maybe it's related to Lazy Loading, and because my collection is part of a ViewModel, when I go to loop through the Photos property within the ViewModel type, it goes to get those records at that point?

Does anyone have any idea what is happening here? The site functions perfectly, but NHProf just sees that it's doing something from where it shouldn't be doing it?!

marcusstarnes
  • 6,393
  • 14
  • 65
  • 112

2 Answers2

4

You haven't shown how your Photos collection is being populated, but I assume it's as simple as viewModel.Photos = entity.Photos. If that's correct (or something similar), then you're just assigning the lazy-loaded entity collection to your view model.

There are several ways to tackle this, but they're all essentially the same: you need to trigger the loading of your collection before you populate your view model. The easiest way to do it is to just stick a .ToArray() or equivalent onto the collection you're assigning; that'll force a fetch.

James Gregory
  • 14,173
  • 2
  • 42
  • 60
  • Thanks James. I've updated my original post to clarify how the Photos collection is being populated (as per your correct assumption). – marcusstarnes Dec 17 '10 at 13:31
  • Unfortunately, I have tried your suggestion of calling .ToArray() against the Photos collection that's assigned to my ViewModel (I've tried it both on the photos collection BEFORE it gets assigned to my ViewModel and AFTER on the ViewModel Photos property, but still no joy. Getting the same warning in NHProf. Any other suggestions? – marcusstarnes Dec 17 '10 at 14:10
  • If that isn't working, then there's a good chance it's something on the `Photo` itself that's lazy loaded rather than the `Photo` collection itself. To be honest, I'd recommend against using your entities in your views at all and favour projecting to a `PhotoViewModel` or something similar. – James Gregory Dec 17 '10 at 14:34
  • Sorry if I misunderstand your suggestion, but isn't that what I'm already doing? I'm using a ViewModel (PhotoViewModel) and using that ViewModel within my view? Obviously that ViewModel itself does currently contain a Photo (entity) and a collection of Photo(entity), but aside from creating a ViewModel with all the same properties as my Photo entity and then assigning my Photo (entity) properties to each corresponding property within the ViewModel, I'm not sure if that's what you mean? – marcusstarnes Dec 17 '10 at 15:58
  • Sorry, my naming was a bit ambiguous. My suggestion was because you have a view model that references your entities. Generally, entities contain more data than the views you're presenting them in (unless you're doing a pure CRUD application), so it's often a good idea to create a view model that represents only what's used in the view. You can use NHibernate transformers and projections to deal with this, or a project like [AutoMapper](http://automapper.codeplex.com/). – James Gregory Dec 17 '10 at 16:47
1

You are right. It is related to Lazy loading. Try to load Photos eagerly. And check their relations. Maybe they have some with eager loading, you don't need, or you are trying to use associated entity in your view.

Aleksei Anufriev
  • 3,206
  • 1
  • 27
  • 31
  • I'm new to NHibernate so forgive my ignorance. At present I have default-lazy set to true within my HBM XML mapping file (within the opening tag. I don't have any other reference to lazy-loading anywhere else within my entire application. – marcusstarnes Dec 17 '10 at 14:12
  • you can turn it off explictly: – Aleksei Anufriev Dec 18 '10 at 07:55