I'm currently learning .Net MVC with C#. I'm very curious as to how people use their Entity Framework contexts. Several related questions are listed below. I hope you can provide feedback.
Should contexts be instantiated in controllers? In models? In another layer of abstraction altogether? What would be the proper encapsulation?
When doing simple CRUD operations, should the call to say context.Add(entity) be called in the controller?
When creating queries to the context, should these queries be done in the controller? Or in the model? Should these use static methods if used in the model?
I hope my questions are quite clear. In general I'm interested how one should interact with a database, and how to abstract that properly from the application. Any info or advice related to that is welcome.
All depends on size of your application. But for large applications you usually do not instantiate any dependencies in controllers. It makes your code tightly coupled to some specific data access provider implementation. What if you will move to MongoDB tomorrow? Think about which places you will need to change in your application.
Same relates to mocks of data access provider when you do unit testing of controllers. You should be able to switch real object, which does persistence in your application, with some mocked implementation. That will be impossible (or at least very hard) if you will make your controllers depend on context and if you will instantiate context in controllers.
Traditional approach is following:
Thus your controller will know only about abstraction, it will be easy to change data access provider (just create repository for MongoDB and give that implementation to controller) also it will be easy to give mocked implementation of data access provider, when you do unit testing of controllers.
Sample:
public class SalesController : Controller
{
private IOrderRepository _repository; // depend on interface
// inject some implementation of dependency into controller
public SalesController(IOrderRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
var orders = _repository.FindAll();
return View(orders);
}
}
The only place where you will use concrete repository implementation, is configuration of dependency injection framework, it's very easy to change implementation:
Bind<DbContext>().To<ShopEntities>();
Bind<IOrderRepository>().To<EFOrderRepository>();
Also it's very easy to do unit testing:
[Test]
public void ShoulReturnAllOrders()
{
List<Order> orders = CreateListOfOrders();
var mock = new Mock<IOrderRepository>();
mock.Setup(r => r.FindAll()).Returns(orders);
var controller = new SalesController(mock.Object);
var result = (ViewResult)controller.Index();
mock.VerifyAll();
Assert.That(result.Model, Is.EqualTo(orders));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With