patterncsharpMinor
Is this correct usage of Repository + Unit of Work + Service Pattern
Viewed 0 times
thisusageservicecorrectrepositoryworkpatternunit
Problem
I have project where I need to use C# and Entity Framework.
After my question here, I have decided to use Unit of Work and Repository patterns.
This is the first time when I'm using this. Can anyone tell me if I'm doing this right or I have to redesign something?
BTW: why do I have to set
Entities:
Context:
Repository:
```
namespace Repository {
public class GenericRepository where TEntity : BaseEntity {
internal StorageContext context;
internal DbSet dbSet;
public GenericRepository(StorageContext context) {
this.context = context;
this.dbSet = context.Set();
}
public virtual IEnumerable Get(
Expression> filter = null,
Func, IOrderedQueryable> orderBy = null,
string includeProperties = "") {
IQueryable query = dbSet
After my question here, I have decided to use Unit of Work and Repository patterns.
This is the first time when I'm using this. Can anyone tell me if I'm doing this right or I have to redesign something?
BTW: why do I have to set
student.Group = null in Service.StudentService.Update()? Without this I'm getting exception. I don't understand when should I use student.Group, and when student.GroupId.Entities:
namespace Model {
public abstract class BaseEntity {
[Timestamp]
public Byte[] TimeStamp{get; set;}
}
}
namespace Model {
public class Group : BaseEntity {
[Key]
public int GroupId {get; set;}
public string Name {get; set;}
public virtual ICollection Students {get; set;}
}
}
namespace Model {
public class Student : BaseEntity {
[Key]
public int StudentId {get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
public string IndexNo {get; set;}
public int GroupId {get; set;}
[ForeignKey("GroupId")]
public virtual Group Group {get; set;}
public virtual ICollection Registrations {get; set;}
}
}Context:
namespace Model {
public class StorageContext : DbContext {
public DbSet Groups {get; set;}
public DbSet Students {get; set;}
...
}
}Repository:
```
namespace Repository {
public class GenericRepository where TEntity : BaseEntity {
internal StorageContext context;
internal DbSet dbSet;
public GenericRepository(StorageContext context) {
this.context = context;
this.dbSet = context.Set();
}
public virtual IEnumerable Get(
Expression> filter = null,
Func, IOrderedQueryable> orderBy = null,
string includeProperties = "") {
IQueryable query = dbSet
Solution
That looks pretty good but it depends on what your controller looks like.
There is a valid argument that the Entity Framework implements the Repository Pattern for you and all you need to implement is the service layer.
So you could put the service layer directly on top of the dbSet. Since I started using just the service layer without the repo pattern directly (so the service layer accesses DbSet) I have not had any problems.
DbSet == Repository
DbContext == Unit of Work
Here is what a controller with the repo looks like. If yours is similar I would say that your code is correct.
Cheeseburger Controller
ICheeseburgerRepository
CheeseburgerRepository With CRUD
```
public class CheeseburgerRepository : ICheeseburgerRepository
{
private SkimosContext context = new SkimosContext();
public CheeseburgerRepository(SkimosContext context)
{
this.context = context;
}
public IQueryable Cheeseburgers
{
get { return context.Cheeseburgers; }
}
public IEnumerable GetCheeseburgers()
{
return context.Cheeseburgers.ToList();
}
public Cheeseburger GetCheeseburgerById(int? id)
{
return context.Cheeseburgers.Find(id);
}
public void InsertCheeseburger(Cheeseburger cheeseburger)
{
context.Cheeseburgers.Add(cheeseburger);
}
public void DeleteCheeseburger(int cheeseburgerId)
{
Cheeseburger cheeseburger = context.Cheeseburgers.Find(cheeseburgerId);
context.Cheeseburgers.Remove(cheeseburger);
}
public void UpdateCheeseburger(Cheeseburger cheeseburger)
{
context.Entry(cheeseburger).State = System.Data.Entity.EntityState.Modified;
}
public void Save()
{
context.SaveChanges();
}
private bool disposed;
protected virtual void Dispose(bool disposing)
There is a valid argument that the Entity Framework implements the Repository Pattern for you and all you need to implement is the service layer.
So you could put the service layer directly on top of the dbSet. Since I started using just the service layer without the repo pattern directly (so the service layer accesses DbSet) I have not had any problems.
DbSet == Repository
DbContext == Unit of Work
Here is what a controller with the repo looks like. If yours is similar I would say that your code is correct.
Cheeseburger Controller
namespace WickedAwesomeWebApp
{
public class CheeseburgerController : Controller
{
public UnitOfWork unitOfWork = new UnitOfWork();
public CheeseburgerRepository cheeseburgerRepository = new CheeseburgerRepository(new MyDbContext());
public ViewResult Index()
{
var viewModel = new CheeseburgerViewModel();
viewModel.Cheeseburger = unitOfWork.CheeseburgerRepository.Get();
return View(viewModel);
}
// GET: /Cheeseburger/Details/5
public ViewResult Details(int id)
{
return View(unitOfWork.CheeseburgerRepository.GetById(id));
}
// GET: /Cheeseburger/Create
public ActionResult Create()
{
return View();
}
// POST: /Cheeseburger/Create
[HttpPost]
public ActionResult Create ([Bind(Include = {CheeseburgerId,/*Include Object Properties to Bind*/{)]Cheeseburger cheeseburger)
{
if (ModelState.IsValid) {
unitOfWork.CheeseburgerRepository.Insert(cheeseburger);
unitOfWork.CheeseburgerRepository.Update(cheeseburger);
return RedirectToAction({Index{);
} else {
return View();
}
}
// GET: /Cheeseburger/Edit/5
public ActionResult Edit(int id)
{
return View(unitOfWork.CheeseburgerRepository.GetById(id));
}
// POST: /Cheeseburger/Edit/5
[HttpPost]
public ActionResult Edit(Cheeseburger cheeseburger)
{
if (ModelState.IsValid) {
unitOfWork.CheeseburgerRepository.Update(cheeseburger);
unitOfWork.Save();
return RedirectToAction({Index{);
} else {
return View();
}
}
// GET: /Cheeseburger/Delete/5
public ActionResult Delete(int id)
{
return View(unitOfWork.CheeseburgerRepository.GetById(id));
}
// POST: /Cheeseburger/Delete/5
[HttpPost, ActionName({Delete{)]
public ActionResult DeleteConfirmed(int id)
{
unitOfWork.MealRepository.Delete(id);
unitOfWork.Save();
return RedirectToAction({Index{);
}
protected override void Dispose(bool disposing)
{
if (disposing) {
unitOfWork.Dispose();
}
base.Dispose(disposing);
}
}
}ICheeseburgerRepository
namespace WickedAwesomeWebApp
{
public interface ICheeseburgerRepository : IDisposable
{
IQueryable Cheeseburgers { get; }
IEnumerable GetCheeseburgers();
Cheeseburger GetCheeseburgerById(int? id);
void InsertCheeseburger(Cheeseburger id);
void DeleteCheeseburger(int cheeseburgerId);
void UpdateCheeseburger(Cheeseburger cheeseburger);
void Save();
new void Dispose();
}CheeseburgerRepository With CRUD
```
public class CheeseburgerRepository : ICheeseburgerRepository
{
private SkimosContext context = new SkimosContext();
public CheeseburgerRepository(SkimosContext context)
{
this.context = context;
}
public IQueryable Cheeseburgers
{
get { return context.Cheeseburgers; }
}
public IEnumerable GetCheeseburgers()
{
return context.Cheeseburgers.ToList();
}
public Cheeseburger GetCheeseburgerById(int? id)
{
return context.Cheeseburgers.Find(id);
}
public void InsertCheeseburger(Cheeseburger cheeseburger)
{
context.Cheeseburgers.Add(cheeseburger);
}
public void DeleteCheeseburger(int cheeseburgerId)
{
Cheeseburger cheeseburger = context.Cheeseburgers.Find(cheeseburgerId);
context.Cheeseburgers.Remove(cheeseburger);
}
public void UpdateCheeseburger(Cheeseburger cheeseburger)
{
context.Entry(cheeseburger).State = System.Data.Entity.EntityState.Modified;
}
public void Save()
{
context.SaveChanges();
}
private bool disposed;
protected virtual void Dispose(bool disposing)
Code Snippets
namespace WickedAwesomeWebApp
{
public class CheeseburgerController : Controller
{
public UnitOfWork unitOfWork = new UnitOfWork();
public CheeseburgerRepository cheeseburgerRepository = new CheeseburgerRepository(new MyDbContext());
public ViewResult Index()
{
var viewModel = new CheeseburgerViewModel();
viewModel.Cheeseburger = unitOfWork.CheeseburgerRepository.Get();
return View(viewModel);
}
// GET: /Cheeseburger/Details/5
public ViewResult Details(int id)
{
return View(unitOfWork.CheeseburgerRepository.GetById(id));
}
// GET: /Cheeseburger/Create
public ActionResult Create()
{
return View();
}
// POST: /Cheeseburger/Create
[HttpPost]
public ActionResult Create ([Bind(Include = {CheeseburgerId,/*Include Object Properties to Bind*/{)]Cheeseburger cheeseburger)
{
if (ModelState.IsValid) {
unitOfWork.CheeseburgerRepository.Insert(cheeseburger);
unitOfWork.CheeseburgerRepository.Update(cheeseburger);
return RedirectToAction({Index{);
} else {
return View();
}
}
// GET: /Cheeseburger/Edit/5
public ActionResult Edit(int id)
{
return View(unitOfWork.CheeseburgerRepository.GetById(id));
}
// POST: /Cheeseburger/Edit/5
[HttpPost]
public ActionResult Edit(Cheeseburger cheeseburger)
{
if (ModelState.IsValid) {
unitOfWork.CheeseburgerRepository.Update(cheeseburger);
unitOfWork.Save();
return RedirectToAction({Index{);
} else {
return View();
}
}
// GET: /Cheeseburger/Delete/5
public ActionResult Delete(int id)
{
return View(unitOfWork.CheeseburgerRepository.GetById(id));
}
// POST: /Cheeseburger/Delete/5
[HttpPost, ActionName({Delete{)]
public ActionResult DeleteConfirmed(int id)
{
unitOfWork.MealRepository.Delete(id);
unitOfWork.Save();
return RedirectToAction({Index{);
}
protected override void Dispose(bool disposing)
{
if (disposing) {
unitOfWork.Dispose();
}
base.Dispose(disposing);
}
}
}namespace WickedAwesomeWebApp
{
public interface ICheeseburgerRepository : IDisposable
{
IQueryable Cheeseburgers { get; }
IEnumerable GetCheeseburgers();
Cheeseburger GetCheeseburgerById(int? id);
void InsertCheeseburger(Cheeseburger id);
void DeleteCheeseburger(int cheeseburgerId);
void UpdateCheeseburger(Cheeseburger cheeseburger);
void Save();
new void Dispose();
}public class CheeseburgerRepository : ICheeseburgerRepository
{
private SkimosContext context = new SkimosContext();
public CheeseburgerRepository(SkimosContext context)
{
this.context = context;
}
public IQueryable Cheeseburgers
{
get { return context.Cheeseburgers; }
}
public IEnumerable GetCheeseburgers()
{
return context.Cheeseburgers.ToList();
}
public Cheeseburger GetCheeseburgerById(int? id)
{
return context.Cheeseburgers.Find(id);
}
public void InsertCheeseburger(Cheeseburger cheeseburger)
{
context.Cheeseburgers.Add(cheeseburger);
}
public void DeleteCheeseburger(int cheeseburgerId)
{
Cheeseburger cheeseburger = context.Cheeseburgers.Find(cheeseburgerId);
context.Cheeseburgers.Remove(cheeseburger);
}
public void UpdateCheeseburger(Cheeseburger cheeseburger)
{
context.Entry(cheeseburger).State = System.Data.Entity.EntityState.Modified;
}
public void Save()
{
context.SaveChanges();
}
private bool disposed;
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
context.Dispose();
}
}
disposed = true;
}
public void Dispose()
{
if (context != null) context.Dispose();
}
}
}Context
StackExchange Code Review Q#36738, answer score: 2
Revisions (0)
No revisions yet.