Reputation: 1045
How should I instantiate the datacontext (entity fw) in a MVC Controller:
In WebForms I would use c), because b) would maintain the db object state across events, which is usually not what I want.
I actually never used a).
Upvotes: 1
Views: 1118
Reputation: 1
Unless this is a very small application or has only a few users; or the lifetime of the application is short, I would never put the any data access "like" code in a UI layer. You just made a design decision that will impact the maintainability and testability of the application.
I like the idea of using a repository pattern with dependency injection - this has proven to work very well. In fact, the current application I work on processes over 11 billion web requests each month against 7 different database instances of MySQL using this pattern.
Another suggestion, implement a service/business layer under the UI. One of the responsibilities of this layer is to provide an API for business processing and database transactions. I usually implement the repository in the business layer, but it references and uses a data access layer component for the actual database-specific transactions. This way you have an abstraction of data access in your business layer - this is a good thing, because a long-lived application will many changes in data access. With this nice abstraction in place, you can use Entity Framework or any other database technology, like NoSQL. Also, using DI, interface/abstract classes allow you to inject the instance of the "repository" into the business component - this certainly improves the testability of your application: so fully unit test your application with a mocking framework (NUnit + Moq).
Hope this helps.
Upvotes: 0
Reputation: 43087
The recommended approach is to use a persistence agnostic data access pattern such as the Repository Pattern. The basic idea is to create controller specific interfaces that abstract away your data access.
public interface ICatalogRepository : IRepository
{
Category GetCategory(int id);
Product GetProduct(int id);
void Add(Product product);
IEnumerable<Category> Categories { get; }
IEnumerable<Supplier> Suppliers { get; }
}
public class CatalogRepository : ICatalogRepository
{
private YourDbContext _db;
public CatalogRepository(YourDbContext db)
{
_db = db;
}
public Category GetCategory(int id)
{
return _db.Categories.Find(id);
}
/* ... */
}
Then you would use an instance of ICatalogRepository
in your controller - it won't have any knowledge of Entity Framework. See Using the unit of work-per-request pattern in ASP.NET MVC for a complete example.
Upvotes: 0
Reputation: 218762
Have a private variable which is an object of your Repositary Interface and Instantiate it in your constructor. you can use that in all your action methods now
public class ItemsController : Controller
{
private IRepositary repo;
public ItemsController()
{
repo = new Repositary(new YourDBContext());
}
public ActionResult Edit(int id)
{
var item=repo.GetItemById(id);
//if needed, map to your view model and return that to the view
// instead of model object to the view
return View(item);
}
}
Upvotes: 0
Reputation: 16145
I'd like to start by saying that I 100% agree with @jrummell in that the DbContext should be instantiated. However, if you aren't going to do that, I would use a private readonly field and provide two constructors:
public MyController() : this(new DbContext()) { }
public MyController(DbContext context)
{
this._dbContext = context;
}
This way you can still inject a DbContext for testing.
Upvotes: 0
Reputation: 12705
you should probably make use of the repository pattern
with dependency injection
passing in the context through the constructor
and with it you will have to use a toll like Unity to Inject the Context in the constructor
Upvotes: 2