1

Advocation for using blocks with Entity Framework seems to be popular, but this tutorial for MVC show the Object Context for the Entity being created once at the class level. I ran into the latter first, so I had been using it. I am now trying to switch to the using block method to see if it really is faster, but am running into this error on the view:

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

The view is trying to access a collection that was created by this:

 homeView.UserList = new SelectList((from n in db.Users where n.US_INACTIVE == 0 orderby n.US_FULL_NAME select n).AsEnumerable(), "US_USER_ID", "US_FULL_NAME");

I don't understand why it is still trying to access the object context from the view (when it uses that SelectList) when it should have been populated in the controlled. Even more confusing, is this same problem does not occur for other database-populated data, which appears to make it into the view just fine.

That aside though, what do I need to do to get data from a using block into the view properly? Or, is a using block the wrong way to go for MVC, and should I just keep using once object context for the class?

Community
  • 1
  • 1
Kyeotic
  • 19,697
  • 10
  • 71
  • 128

2 Answers2

3

You probably didn't call .ToList at the end of your expression so you are not eagerly executing any query but only building query expressions. It is only once the view is executed that the query is implicitly executed, but that happens long after your controller life has ended as well as any data contexts.

This being said I consider passing domain models to views as a bad practice. You should be using view models which are classes specifically designed to the requirements of a given view.

Ayende Rahien has a series of blog posts about the issues of view models. The view model that you pass to the view from the controller must contain all the necessary properties eagerly initialized and loaded with data and this independently of the data access technology you are using. And by the way it's not the controller's responsibility to manage your EF data contexts lifetime. That's should be specific to your data access layer (the repository).

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • It actually is a ViewModel. The UserList property is SelectList, as shown by the second code block. Does AsEnumerable not execute the query? Is ToList the right method to call in this example? – Kyeotic Aug 01 '11 at 21:28
  • Also, I am not clear on what you mean by the repository's responsibility to manage lifetime. If EF does not manage this, how is it done? – Kyeotic Aug 01 '11 at 21:30
  • @Tyrsius, `AsEnumerable` doesn't execute the query, it returns an `IEnumerable` from the lambda expression. By repository I mean the Repository Pattetn. It is a separate class that you write implementing some common interface that your controller works with. Of course the specific implementation (EF in your case) is injected into the controller using a DI framework, so that inside your controller you should never be writing any using statements managing any DataContextss. A controller should not even know what a DataContext is... – Darin Dimitrov Aug 01 '11 at 21:53
  • ... That's a specific notion of the data access technology you are currently using (EF in your case). A controller should work with domain models, view models, invoke methods on repositories and services. – Darin Dimitrov Aug 01 '11 at 21:53
  • @Darrin, so when using MVC, I should NOT use using blocks? – Kyeotic Aug 01 '11 at 22:07
  • generally in web development you can turn lazy loding off (inefficient). and without lazy you can use using bocks. poplate all properties with eagerloading (include) inside of the block... – benwasd Aug 02 '11 at 06:18
1

Are you using another table in your view that is related to Users? In your current query only the Users table will be populated and accessing data in any related table will throw that error.

homeView.UserList = new SelectList((from n in db.Users.Include("Other Table") where n.US_INACTIVE == 0 orderby n.US_FULL_NAME select n).AsEnumerable(), "US_USER_ID", "US_FULL_NAME");
Tija
  • 1,691
  • 4
  • 20
  • 33
  • That's very interesting, but it was not the issue. Thank you though, that will probably be helpful in the future – Kyeotic Aug 01 '11 at 22:11