I currently been assigned to a asp mvc project using entity framework. This will be a Line of Business application. I want to develop this app using repository and unit of work pattern. I'm new to this pattern (and new to .net too) and i am having a problem in understanding the pattern and how to implement it.
I have read numerous articles and i think this is how my application should be
Entity Framework -> Repository -> Unit of Work -> Client (Asp MVC)
I attach some code from this article http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
using System;
using ContosoUniversity.Models;
namespace ContosoUniversity.DAL
{
public class UnitOfWork : IDisposable
{
private SchoolContext context = new SchoolContext();
private GenericRepository<Department> departmentRepository;
private GenericRepository<Course> courseRepository;
public GenericRepository<Department> DepartmentRepository
{
get
{
if (this.departmentRepository == null)
{
this.departmentRepository = new GenericRepository<Department>(context);
}
return departmentRepository;
}
}
public GenericRepository<Course> CourseRepository
{
get
{
if (this.courseRepository == null)
{
this.courseRepository = new GenericRepository<Course>(context);
}
return courseRepository;
}
}
public void Save()
{
context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
Unit of Work will have repositories and will create DBContext upon creation
So controller will create Unit of Work upon creation. To Show data i will use this code
var department = UoW.departmentRepository.Find(1);
return View(department);
and when client click save button, i will run this code
UoW.departmentRepository.Update(department);
UoW.Save();
My question:
What if it takes hours from data retrieval until the client click save button. From what i know, we have to keep context as short as possible.
Where should i put business logic? Do i put it in repository? So i would call UoW.departmentRepository.Validate(department) before save. But then, what if i need to validate entity which relate to other entity. Do i call UoW.departmentRepository.Validate(course, department)?
Is there a complete sample project for this kind of application?
EDIT
As Ant P adviced, i need to add another layer to put my business logic.
This is what i have come so far
Unit Of Work:
public class UnitOfWork : IDisposable
{
private DBContext _context = new DBContext();
public DBContext Context
{
get
{
return this._context;
}
}
public void Save()
{
_context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
Business Logic:
public class SalesBusinessLogic : IDisposable
{
private ICustomerRepository _customerRepo;
private ISalesRepository _salesRepo;
private UnitOfWork _uow;
public SalesBusinessLogic(UnitOfWork uow)
{
this._uow = uow;
}
public ICustomerRepository CustomerRepo
{
get
{
if (this._customerRepo == null)
{
this._customerRepo = new CustomerRepository(this._uow);
}
return this._customerRepo;
}
}
public ISalesRepository SalesRepo
{
get
{
if (this._salesRepo == null)
{
this._salesRepo = new SalesRepository(this._uow);
}
return this._salesRepo;
}
}
public bool Validate(Sales sales)
{
//this is where validation performed
return true;
}
}
Controller:
public SalesController : Controller
{
private UnitOfWork _uow = new UnitOfWork();
private SalesBusinessLogic _bl = new SalesBusinessLogic(this._uow);
public ActionResult Index()
{
var sales = _bl.SalesRepo.Find(1);
sales.CustomerID = 1;
if _bl.Validate(sales)
{
_bl.SalesRepo.Update(sales);
_uow.Save();
}
return View(sales);
}
}
Here UnitOfWork act only as provider of dbcontext, which will be consumed by business logic and repository. Repository will be in BusinessLogic class.
Server side validation will be handled by BusinessLogic and client side validation will be handled by viewmodel in Web Layer.
My only concern is that dbcontext in UnitofWork is publicly accessible.
Am i in the right direction here?
What if it takes hours from data retrieval until the client click save button. From what i know, we have to keep context as short as possible.
This isn't an issue - the controller is instantiated per request. It doesn't persist while the user views the page. It sounds like you're misunderstanding at what point the controller is instantiated. When you instantiate the UnitOfWork within the controller's constructor, the process flow goes like this:
Where should i put business logic? Do i put it in repository? So i would call UoW.departmentRepository.Validate(department) before save. But then, what if i need to validate entity which relate to other entity. Do i call UoW.departmentRepository.Validate(course, department)?
Typically, your business logic would be abstracted into a separate layer that sits between your web application and your repositories. Tutorials that show you repositories injected directly into controllers assume that you have "thin" business logic.
However, validation definitely isn't the job of a repository. You should create a separate view model for each view and validate those in your controller. The repository should be used pretty much solely for CRUD operations.
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