What would be the reason for implementing UOW on top of DbContext if it already internally implements UOW?
Here is the structure I have now, just looking for advice as to whether or not this is following best practices. I am not posting all code for the project, just concentrating on Users and Roles for now. Here is some of the project structure
outhowz42
Member
80 Points
121 Posts
Re: UnitOfWork pattern question
May 31, 2012 02:29 PM|LINK
What would be the reason for implementing UOW on top of DbContext if it already internally implements UOW?
Here is the structure I have now, just looking for advice as to whether or not this is following best practices. I am not posting all code for the project, just concentrating on Users and Roles for now. Here is some of the project structure
Folder >> Files:
Controllers >> AccountController, UsersController, RoleController
DAL >> DataContext, DataContextInitializer, IUserRepository, UserRepository, IRoleRepository, RoleRepository, UnitOfWork
Models >> AccountModels, User, Role
ViewModels >> RoleViewModel, UserEditViewModel
//LEAVING OUT MOST ACTION RESULT METHODS FOR BREVITY... public class UserController : Controller { private UnitOfWork unitOfWork = new UnitOfWork(); // // GET: /User/ public ActionResult Index() { return View(unitOfWork.UserRepository.GetUsers()); } // // GET: /User/Edit/5 public ActionResult Edit(Guid id) { User user = unitOfWork.UserRepository.GetUserByID(id); if (user == null) { return HttpNotFound(); } return View(new UserEditViewModel(user, unitOfWork.RoleRepository.GetRoles())); } // // POST: /User/Edit/5 [HttpPost] public ActionResult Edit(UserEditViewModel userEditViewModel) { if (ModelState.IsValid) { unitOfWork.UserRepository.UpdateUser(userEditViewModel); unitOfWork.Save(); return RedirectToAction("Index"); } return View(unitOfWork.UserRepository.GetUserByID(userEditViewModel.UserId)); } protected override void Dispose(bool disposing) { unitOfWork.Dispose(); base.Dispose(disposing); } } public interface IUserRepository : IDisposable { IEnumerable<User> GetUsers(); User GetUserByID(Guid userID); void InsertUser(User user); void DeleteUser(Guid userID); void UpdateUser(User user); void Save(); } public class UserRepository : IUserRepository, IDisposable { #region Member Fields private DataContext context; #endregion #region Constructor(s) public UserRepository(DataContext context) { this.context = context; } #endregion #region IUserRepository Members public IEnumerable<User> GetUsers() { return context.Users.OrderBy(u => u.LastName).OrderBy(u => u.FirstName).ToList(); } public User GetUserByID(Guid userID) { return context.Users.Find(userID); } public void InsertUser(User user) { context.Users.Add(user); } public void DeleteUser(Guid userID) { User user = context.Users.Find(userID); context.Users.Remove(user); } public void UpdateUser(User user) { context.Entry(user).State = EntityState.Modified; } public void UpdateUser(UserEditViewModel userEditViewModel) { User user = GetUserByID(userEditViewModel.UserId); user.UserName = userEditViewModel.UserName; user.Email = userEditViewModel.Email; user.FirstName = userEditViewModel.FirstName; user.LastName = userEditViewModel.LastName; user.PhoneExtension = userEditViewModel.PhoneExtension; user.IsApproved = userEditViewModel.IsApproved; foreach (RoleViewModel rvm in userEditViewModel.RoleViewModels) { if (rvm.Checked) { //add role if it doesn't exist var roleToAdd = (from role in context.Roles where role.RoleId.Equals(rvm.Id) select role).First(); if (roleToAdd != null) user.Roles.Add(roleToAdd); } else { //remove role var roles = from role in user.Roles where role.RoleId.Equals(rvm.Id) select role; if (roles.Count() == 1) user.Roles.Remove(roles.ElementAt(0)); } } context.Entry(user).State = EntityState.Modified; } public void Save() { context.SaveChanges(); } #endregion //disposal stuff removed for brevity }public class UnitOfWork : IDisposable { #region Member Fields private DataContext context = new DataContext(); #endregion #region Properties public RoleRepositoroy RoleRepository { get { if (_roleRepository == null) _roleRepository = new RoleRepositoroy(context); return _roleRepository; } }private RoleRepositoroy _roleRepository; public UserRepository UserRepository { get { if (_userRepository == null) _userRepository = new UserRepository(context); return _userRepository; } }private UserRepository _userRepository; #endregion #region Methods public void Save() { context.SaveChanges(); } #endregion #region IDisposable Members 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); } #endregion }Now just a few questions.
1. In my UserController I declare a UnitOfWork. I believe I should be injecting this into the controller instead for testability. How can I do that?
2. Is it OK if my repository knows about my UserEditViewModel?
3. Should UnitOfWork be an IUnitOfWork instead that my DataContext implements?
4. Is it pointless to use repositories and IRepositiory? Should I just be using the DbSets in the DataContext class?
Thanks!!