Best practises in MVC for not disposing the object context? - asp.net-mvc

I have an Entity Framework class called Student. It has a list of Classes. Now, everytime I (from my view) refer to ViewBag.Student.Classes, it fails with an object disposed exception, because my controller looks like this:
using(var myObjectContext = new ModelContainer()) {
ViewBag.Student = myObjectContext.UserSet.OfType<Student>().FirstOrDefault(s => s.Id == ActiveStudentSignedIn);
}
Now, I know I could just pass in the student's classes in the viewbag too, but that would increase complexity when using strong-typed partial views that rely on a student and its details.
I think it would be wrong to not having the "using" keyword there, because wouldn't that leave up too much garbage for the garbage collector to collect?
I'm obviously doing something wrong. But what?

There are two ways to solve this:
Use eager loading (Include method in query) and pass all data you need in view from your controller action directly. Currently you receive exception because your view is trying to trigger lazy loading and execute another queries to database but the context is already disposed.
Extend lifetime of your context = don't create context per action. Create single context per controller (new instance is created for every request) and dispose context in controller's Dispose method. You can also inject the context into controller from outside - dependency injection but that would require some other infrastructure.

You could try eagerly loading associations:
ViewBag.Student = myObjectContext
.UserSet
.Include("Classes")
.OfType<Student>()
.FirstOrDefault(s => s.Id == ActiveStudentSignedIn);

Related

Handling transaction with UnitOfWork and EF

I'm using Entity Framework 5.0 and MVC4. I have couple of domains. Each of them has its own DbContext (which uses appropriate tables), repository and service. I also implemented UnitOfWork.
Handling specific flow in transaction inside one service for specific domain is simple. I'm doing some operations on tables and at the end I'm invoking UnitOfWork.Save, which behaves as Transaction.Commit.
But lets assume I have a case in which I have to invoke operations for two different domains and this two operations must be put inside one transaction. I have access to services for domains from controller so this actions are invoked from there. At the moment I can see three solutions:
I must have UnitOfWork in controller and call Save method at the end (I don't like this idea).
Create some service in which I will have UnitOfWork and access to both services (actually it is the same solution as above, but I'm moving logic to separate class)
I have to create additional TransactionScope inside controller and commit it at the end
Please let me know what option you think is the best. If you have any other than the three above, let me know. Or maybe something is wrong with my concept? I mean domains and their db contexts?
Assuming your UnitOfWork implementation supports normal Transactions in .NET, you can do the following and they should enroll in the currently running transaction.
protected TransactionScope CreateTransactionScope()
{
var options = new TransactionOptions();
options.IsolationLevel = IsolationLevel.ReadCommitted;
options.Timeout = TransactionManager.MaximumTimeout;
return new TransactionScope(TransactionScopeOption.Required, options);
}
using (var scope = this.CreateTransactionScope())
{
// do operations with context 1
// do operations with context 2
scope.Complete();
}

What is the correct place to dispose a repository created in a custom controller factory?

In my ASP.NET MVC project I use a custom controller factory that instantiates an Entity Framework-based data repository and passes it to the controller's constructor. The repository object implements IDisposable, but where should I call its Dispose method? The most straightforward approach that comes to mind is to override the controller's Dispose method and do it there, but since the repository was injected into the controller and not created there, disposing it in the controller doesn't seem quite right to me.
In your repository, you should use the Entity Framework data contexts within a using statement. This means that after the data access is finished the Dispose method will be called on the context, closing the connection.
using(var context = new MyDbContext())
{
//do your data access
}
I guess is a little late by now, but you do it in the ReleaseController method of your IControllerFactory.
Take a look at this: http://www.jasinskionline.com/technicalwiki/(S(wvw00ibwlzs5na45orv53qyl))/Custom-Controller-Factory-Putting-Controllers-in-an-External-Assembly-ASP-NET-MVC.ashx?AspxAutoDetectCookieSupport=1

class instance per request in asp.net mvc

I'm new with asp.net mvc. I have an app class which only needs one instance per request. It has IDispose so i'll need it to be dispose properly and I call it every page hit.
The problem I am finding is I sometimes needs to call methods in my view. I have no idea how I can access the class in the controller, view and have it dispose properly at the end of each request. I get the feeling I need to replace ALL of my controllers with my own controller class as a base. But this would only work if it executes the view first and I can access members in MyController from the view (actually I can just stuff it into the viewbag can't I)
Whats the proper way of doing this?
One solution would be to wire up a Dependency Injection framework (such as Ninject) and let it control the object lifetime for you. Ninject has a InRequestScope lifetime policy, which will create one object per request, so subsequent calls to get the object will return the same object if it is in the same request.
After implementing the dependency injection you can dispose your dependencies or objects like below in the controller.
protected override void Dispose(bool disposing)
{
_requestRepository.Dispose();
base.Disposing(disposing);
}

Entity Framework Updating?

How do you update an entity in EF 4?
For example:
1) Use AutoMapper to generate the CategoryEditModel from a Category entity from the Service Layer.
2) Pass the EditModel to the View. Great!!
3) Post back the EditModel, use AutoMapper to take the CategoryEditModel --> Category.
4) Take that Category and pass it off to the Service Layer which passes it off to the Repository which in turn does an ObjectSet.Attach(TEntity).
Tells me the ObjectStateManager has another object with the same key???
I am using Ninject to inject the Controller with the Service and UnitOfWork, the Service with a Repository, the Repository with a UnitOfWork. The UnitOfWork is scoped per request.
It seems something is being held in cache maybe?
Do I have to call dispose on the UOW or will Ninject take care of it? It does implement IDisposable, and in the dispose it disposes of the context.
Entity Contexts cache objects. It's generally considered wise to keep the life of a particular context quite short. I do this by using a factory within each repository method:
public SomeObject GetSomeObjectById(int id)
{
using (var context = _contextFactory.Get())
{
return context.SomeObjects.SelectSingle(o => o.Id == id);
}
}
If you're quite certain that you want to follow the one-context-per-request model, you'll need to load the entity you want out of the context (which should be free if you use context.GetObjectByKey because it sounds like it's cached in this case), change the values on the object, and then save changes.
I think you should use only a single Entity Framework Session object without having repository. Take a look at this post : Question about Interfaces and DI? and let me know if you have questions. It's code-first and it works perfectly for me.
Hope it helps you!

ASP.net MVC Controller - Constructor usage

I'm working on an ASP.net MVC application and I have a question about using constructors for my controllers.
I'm using Entity Framework and linq to Entities for all of my data transactions. I need to access my Entity model for nearly all of my controller actions. When I first started writing the app I was creating an entity object at the beginning of each Action method, performing whatever work I needed to and then returning my result.
I realized that I was creating the same object over and over for each action method so I created a private member variable for the Entity object and started instantiating it in the constructor for each controller. Now each method only references that private member variable to do its work.
I'm still questioning myself on which way is right. I'm wondering A.) which method is most appropriate? B.) in the constructor method, how long are those objects living? C.) are there performance/integrity issues with the constructor method?
You are asking the right questions.
A. It is definitely not appropriate to create this dependencies inside each action method. One of the main features of MVC is the ability to separate concerns. By loading up your controller with these dependencies, you are making the controller for thick. These should be injected into the controller. There are various options for dependency injection (DI). Generally these types of objects can be either injected into the constructor or into a property. My preference is constructor injection.
B. The lifetime of these objects will be determined by the garbage collector. GC is not deterministic. So if you have objects that have connections to resource constrained services (database connections) then you may need to be sure you close those connections your self (instead of relying on dispose). Many times the 'lifetime' concerns are separated out into an inversion of control (IOC) container. There are many out there. My preference is Ninject.
C. The instantiation costs are probably minimal. The database transactions cost are where you probably want to focus your attention. There is a concept called 'unit of work' you may want to look into. Essentially, a database can handle transactions larger than just one save/update operation. Increasing the transaction size can lead to better db performance.
Hope that gets you started.
RCravens has some excellent insights. I'd like to show how you can implement his suggestions.
It would be good to start by defining an interface for the data access class to implement:
public interface IPostRepository
{
IEnumerable<Post> GetMostRecentPosts(int blogId);
}
Then implement a data class. Entity Framework contexts are cheap to build, and you can get inconsistent behavior when you don't dispose of them, so I find it's usually better to pull the data you want into memory, and then dispose the context.
public class PostRepository : IPostRepository
{
public IEnumerable<Post> GetMostRecentPosts(int blogId)
{
// A using statement makes sure the context is disposed quickly.
using(var context = new BlogContext())
{
return context.Posts
.Where(p => p.UserId == userId)
.OrderByDescending(p => p.TimeStamp)
.Take(10)
// ToList ensures the values are in memory before disposing the context
.ToList();
}
}
}
Now your controller can accept one of these repositories as a constructor argument:
public class BlogController : Controller
{
private IPostRepository _postRepository;
public BlogController(IPostRepository postRepository)
{
_postRepository = postRepository;
}
public ActionResult Index(int blogId)
{
var posts = _postRepository.GetMostRecentPosts(blogId);
var model = new PostsModel { Posts = posts };
if(!posts.Any()) {model.Message = "This blog doesn't have any posts yet";}
return View("Posts", model);
}
}
MVC allows you to use your own Controller Factory in lieu of the default, so you can specify that your IoC framework like Ninject decides how Controllers are created. You can set up your injection framework to know that when you ask for an IPostRepository it should create a PostRepository object.
One big advantage of this approach is that it makes your controllers unit-testable. For example, if you want to make sure that your model gets a Message when there are no posts, you can use a mocking framework like Moq to set up a scenario where your repository returns no posts:
var repositoryMock = new Mock<IPostRepository>();
repositoryMock.Setup(r => r.GetMostRecentPosts(1))
.Returns(Enumerable.Empty<Post>());
var controller = new BlogController(repositoryMock.Object);
var result = (ViewResult)controller.Index(1);
Assert.IsFalse(string.IsNullOrEmpty(result.Model.Message));
This makes it easy to test the specific behavior you're expecting from your controller actions, without needing to set up your database or anything special like that. Unit tests like this are easy to write, deterministic (their pass/fail status is based on the code, not the database contents), and fast (you can often run a thousand of these in a second).

Resources