I am working on a project with Entity Framework where i have implemented Repository pattern and DI (Microsoft Unity), now to maintain the database transactions i want to implement the UnitOfWork pattern, but i am totally confused about how shall i implement it in my current project, i google around few posts, but could not find anything doable with my existing project.
Below is the EF and Repository structure along with DI (Microsoft Unity).
Entities:
public class GenericDo
{
public DateTime CreatedDate {get;set;}
public string CreatedBy {get;set;}
}
public class UsersDo : GenericDo
{
public int UserId {get;set;}
public string Username {get;set;}
....
}
public class UserProfileDo : GenericDo
{
public int Id {get;set}
public int UserId {get;set;}
public string Address {get;set;}
....
}
Interface:
public interface IGenericDao : IGenericDao<GenericDo> {}
public interface IGenericDao<T>
{
void Add(T entity);
T Get(object Id);
....
}
public interface IUsersDao : IUsersDao<UsersDo> {}
public interface IUserProfileDao : IUserProfileDao<UserProfileDo>{}
Interface Implementation:
public class GenericDao<T> : IGenericDao<T> where T : class
{
private readonly DataContext context;
public GenericDao(DataContext _context)
{
this.context = _context;
}
public void Add(T entity)
{
context.Set<T>().Add(entity);
}
public T Get(object Id)
{
return context.Set<T>().Find(Id);
}
}
public class UsersDao : GenericDao<UsersDo>, IUsersDao
{
public UsersDao(DataContext context) : base (context){}
}
public class UserPorfileDao : GenericDao<UserProfileDo>, IUserProfileDao
{
public UserPorfileDao(DataContext context) : base (context){}
}
Dependency Injection Setup in Global.asax.
var container = this.AddUnity();
container.RegisterType<IUsersDao, UsersDao>();
container.RegisterType<IUserProfileDao, UserProfileDao>();
Now in my main webpage(ASP.Net)
public partial class Default : System.Web.UI.Page
{
private readonly IUsersDao usersDao;
private readonly IUserProfileDao userProfileDao;
public Default(IUsersDao _userDao, IUserProfileDao _userProfileDao)
{
this.usersDao = _userDao;
this.userProfileDao = _userProfileDao;
}
// Now for testing purpose, i update record.
protected void Page_Load(object sender, EventArgs e)
{
UsersDo user = usersDao.Get(1);
user.Username = "new system";
UserProfileDo userProfile = userProfileDao.Get(1);
userProfile.Address = "new address";
// Now here i am confused about setting up common Save method to update database with transaction.
}
}
EntityFramework's DbContext already implements Unit of Work, so it is not necessary to add yet another layer of abstraction to implement this.
One could even doubt if creating a Repository pattern is actually helpful if you're using Entity Framework. Instead of using a layered architecture and using a Repository, you could investigate whether it is not better to use a more sliced architecture and use the DbContext directly.
Also, what is the benefit of having a 'Generic Dao' that just delegates calls to Entity Frameworks DbContext ? It's just yet another level of abstraction which adds extra complexity but doesn't give you any added value.
Unit of work ecapsulates the database operations in a single object and keeps track of them. In Entity Framework DbContext implements this behaviour and DbSet<> implements the repository. The reason why people create their own wrappers around is to be able to swap Entity Framework for another ORM, if needed or to mock Entity Framework for testing,.
UnitOfWork pattern is used with Entity Framework.
The repository and unit of work patterns are intended to create an abstraction layer between the data access layer and the business logic layer of an application. Implementing these patterns can help insulate your application from changes in the data store and can facilitate automated unit testing or test-driven development (TDD).
First step is to create repositories. Repository is a class which exposes methods to business layer
Second step: You can create UnitOfWork implementation as shown below. There are properties corresponding to every repository. Then you inject Unit of Work in your business layer to use the repository methods.
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;
}
}
}
refer documentation at: https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
Related
I followed an online tutorial of the UnitOfWork pattern with Entity Framework as it has been awhile since I have used it. I am confused as to why in the tutorial the DataContext is a parameter of the public UnitOfWork constructor. This means if I use the UnitOfWork in another layer of the application, the other layer must be aware of the DataContext. This does not seem like a good separation of concerns. Am I missing something?
UnitOfWork:
public class UnitOfWork : IUnitOfWork
{
private readonly PurchasingDataContext _context;
public UnitOfWork(PurchasingDataContext context)
{
_context = context;
Items = new ItemRepository(_context);
Manufacturers = new LabelerRepository(_context);
Quotes = new QuoteRepository(_context);
Vendors = new VendorRepository(_context);
Contacts = new ContactRepository(_context);
}
public IItemRepository Items { get; private set; }
public ILabelerRepository Manufacturers { get; private set; }
public IQuoteRepository Quotes { get; private set; }
public IVendorRepository Vendors { get; private set; }
public IContactRepository Contacts { get; private set; }
public int Complete()
{
return _context.SaveChanges();
}
public void Dispose()
{
_context.Dispose();
}
}
Interface:
public interface IUnitOfWork : IDisposable
{
IContactRepository Contacts { get; }
IItemRepository Items { get; }
ILabelerRepository Manufacturers { get; }
IQuoteRepository Quotes { get; }
IVendorRepository Vendors { get; }
int Complete();
}
I am confused as to why in the tutorial the DataContext is a parameter of the public UnitOfWork constructor.
This is to make injecting the dependency into the UoW possible. By doing this, you can honor SRP easily.
With it, you can manage the scope of DataContext separately outside the UoW. This gives you much flexibility while using same UoW in different scenario (windows application vs web application for example). With this, you can expand database transactions the way you want.
This means if I use the UnitOfWork in another layer of the application, the other layer must be aware of the DataContext.
Yes; but not entirely true. Yes, the instance of DataContext should be managed (create, inject and dispose) by calling layer. That's it. That layer does not need to interact with with this instance in any way.
This does not seem like a good separation of concerns.
In continuation to earlier point, calling layer does not need to know how that instance work. All that part is abstracted in your UoW class. This is clean separation of concerns.
Am I missing something?
Hope you know that now.
I would start by asking why you are creating and exposing these repositories in your UnitOfWork. Having a single class that is responsible for a unit of work and the ownership of all of your repositories violates the Single Responsibility Principle. Your IUnitOfWork exposing every single repository that may or may not be needed by a caller violates the Interface Segregation Principle.
Instead of this approach, you should be using a dependency injection framework to manage the lifetimes of the context, repositories, and unit of work. The framework should ensure that one instance is created per request and shared across dependencies where needed.
A typical EntityFramework UnitOfWork would look similar to:
public interface IUnitOfWork
{
void SaveChanges();
}
with an implementation like:
public class UnitOfWork : IUnitOfWork
{
private readonly PurchasingDataContext _context;
public UnitOfWork(PurchasingDataContext context)
{
_context = context;
}
public void SaveChanges()
{
return _context.SaveChanges();
}
}
I have a data access layer which returns repositories.
For example, I have the following repository interfaces:
I have Entity Framework implementations of these repositories. These implementations get injected at a runtime with Ninject.
I have One controller with multiple repositories given below
IUploadRepository _uploadRepository;
ISalesRepository _salesRepository;
ITRSalesRepository _trsalesRepository;
ILocalPurchaseRepository _localRepository;
with single controller named -HomeController
In order to functional operation , I need to use DBContext into implementation thats why I implement all those interface like given below:
public class UploadRepository : IUploadRepository
{
private readonly XMANEntities _entities;
public UploadRepository(XMANEntities entities)
{
_entities = entities;
}
*here goes all implementation with context for specific*
}
Here now I have a constructor within a HomeController which looks this:
public class HomeController : Controller
{
private IUploadRepository uploadRepository;
public HomeController()
{
this.uploadRepository = new UploadRepository(new XMANContext());
}
public HomeController(IUploadRepository uploadRepository)
{
this.uploadRepository = uploadRepository;
}
}
How can I use others in this controller.Is it bad practice to inject multiple repo's into a controller?
i have tried this way like given below:
public HomeController() : this(new UploadRepository(
new XMANEntities()), new SalesRepository(new XMANEntities()),
new TRSalesRepository(
new XMANEntities()), new LocalPurchaseRepository(new XMANEntities()))
{
}
public HomeController(UploadRepository uploadRepository, SalesRepository salesRepository,
TRSalesRepository trsalesRepository, LocalPurchaseRepository localPurchaseRepository)
{
this.uploadRepository = uploadRepository;
this.salesRepository = salesRepository;
this.trsalesRepository = trsalesRepository;
this.localPurchaseRepository = localPurchaseRepository;
}
It's perfectly acceptable to inject multiple dependencies on an object. However, avoid it as much as possible (Except for transactional objects) to prevent mixing of responsibilities. An approach that you can look at is stored procedures.
private IUploadRepository _uploadRepository;
private ISalesRepository _salesRepository;
private ITRSalesRepository _trsalesRepository;
private ILocalPurchaseRepository _localRepository;
public HomeController(
IUploadRepository uploadRepository,
ISalesRepository salesRepository,
ITRSalesRepository trsalesRepository,
ILocalPurchaseRepository localRepository
)
{
this._uploadRepository = uploadRepository;
this._salesRepository= salesRepository;
this._trsalesRepository= trsalesRepository;
this._localRepository= localRepository;
}
How do you implement the unit of work and repository pattern in MVC 5 and EF6? Previously I've avoided any need for unit of work by using a single repository which was injected into my controller as follows:
public class ProductController : BaseController
{
private IShopRepository _repository;
public ClassController()
: this(new ShopRepository())
{
}
public ClassController(IShopRepository repository)
{
_repository = repository;
}
....
}
But now I want to refactor the code so that I have a separate repository for each entity type eg. ProductRepository, CustomerRepository etc and be able to inject multiple repositories into a controller whilst ensuring the same dbcontext is used.
Reading through the microsoft tutorial on http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/advanced-entity-framework-scenarios-for-an-mvc-web-application, the architects now advise the repository and unit of work pattern are no longer needed but they don't provide any example of how to implement or structure repositories in their examples?
Some people have even started renaming repositories to services?
How do you structure your repositories and implement unit of work in MVC5 using EF6 perhaps using an IOC such as Unity? Or what is another solution?
I'm working along the following lines but not sure if it is best solution and how do i add unit of work?
public class ShopContext : DbContext
{
public ShopContext() : base("name=ShopContext")
{
}
public DbSet<Product> Products { get; set; }
public DbSet<Customer> Customers { get; set; }
...
}
public interface IProductRepository
{
IEnumerable<Product> GetAll();
...
}
public interface ICustomerRepository
{
IEnumerable<Customer> GetAll();
...
}
public class ProductRepository : IDisposable, IProductRepository
{
private ShopContext _context;
public ProductRepository()
{
_context = new ShopContext();
}
public IEnumerable<Product> GetAll()
{
return _context.Products;
}
// Other methods not displayed
protected void Dispose(bool disposing)
{
if (disposing)
{
if (_context != null)
{
_context.Dispose();
_context = null;
}
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
public class CustomerRepository : IDisposable, ICustomerRepository
{
private ShopContext _context;
public CustomerRepository()
{
_context = new ShopContext();
}
public IEnumerable<Customer> GetAll()
{
return _context.Customers;
}
// Other methods not displayed
protected void Dispose(bool disposing)
{
if (disposing)
{
if (_context != null)
{
_context.Dispose();
_context = null;
}
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
public class ProductsController : BaseController
{
private IProductRepository _productRepository;
private ICustomerRepository _customerRepository;
public ProductsController()
: this(new ProductRepository(), new CustomerRepository())
{
}
public ProductsController(IProductRepository productRepository, ICustomerRepository customerRepository)
{
_productRepository = productRepository;
_customerRepository = customerRepository;
}
// Other controller methods not shown.
}
Example code would be helpful.
The best working example one can find is the series of Mr Mittal at codeproject
he is using Entity Framework, Generic Repository pattern and Unit of Work.
keep up with him you'll get to know how this all works
here is the link Mittal Series
As #Thomas has already stated in the comments, I think what you're after here is a service layer rather than a repository. The two terms are often used very interchangeably, but they are not the same thing.
The repository pattern is intended to provide an abstraction of the database so that the database can change without impacting on the rest of the code. The DBContext in EF6 is already doing that for you as you can have, for example, a table called one thing, but mapped to a class with a different name. The DBContext also already implements the Unit of Work pattern, as it will perform all actions inside a single transaction up until you call SaveChanges/SaveChangesAsync on the context.
The service layer then provides methods to the user interface layer. It calls the methods from the repository to do this.
With a simple model it seems like the service layer and the repository are the same thing, but your repository would typically map to one business object (e.g. a Contact) where as your service layer might encapsulate a number of objects (e.g. a Customer business entity, which when saved stores data to the Contact and CustomerProfile repositories), using a unit of work to ensure that both changes are committed or rolled back together.
This excellent existing stack overflow answer by #ken2k goes into this in much more detail.
I want to create an abstraction layer between Entity Framework and the rest of my application. But I am having a few problems with Entity Framework.
Basically (I don't show you all the interface layers that I've created too), I've split my application into several projects like this :
Domain
Contains my domain object, an abstraction of my datastorage object
DAL
Creates a link between my datastorage and my business layer. Contains two types of elements :
Private ones : my EDMX, my database object, and some other generated objects providing me some useful methods like ToDomain/ToEntity
Public ones : my Data Access Object, providing CRUD methods
Business
Contains the logic of my application. Only knows about the public elements of the DAL and the Domain Layer.
Presentation
Presents the domain objects for the user. Only knows about the business layer.
As I said, I want to create an abstraction of my datastorage objects (in my case Database object, but I want a solution that works also for file or WCF storage for example) so that my business layer don't know anything about my DAL implementation.
Here is a glimpse of what I've done in my DAL :
public abstract class GenericDao<TEntity, TDomain, TDbContext> : IGenericDao<TDomain>
where TDbContext : DbContext, new()
where TEntity : class
where TDomain : class
{
protected TDbContext _context;
protected DbSet<TEntity> _dbSet;
public GenericDao(TDbContext dbContext)
{
this._context = dbContext;
this._dbSet = dbContext.Set<TEntity>();
}
public TDomain Create()
{
return this.ToDomain(this._dbSet.Create());
}
public IList<TDomain> GetAll()
{
return this._dbSet.ToList().Select(entity => this.ToDomain(entity)).ToList();
}
public void Update(TDomain domain)
{
var entity = this.ToEntity(domain);
var entry = this._context.Entry(entity);
entry.State = EntityState.Modified;
}
public void Remove(TDomain domain)
{
_dbSet.Remove(this.ToEntity(domain));
}
protected abstract TDomain ToDomain(TEntity entity);
protected abstract TEntity ToEntity(TDomain domain);
}
You will probably see what's wrong with my code by reading it: when I try to delete or update an entity, I am not manipulating an entity attached to Entity Framework. If I try to attach my entity to the dbContext, it fails because there is already an entity in the context with the same id.
I already thought about several solutions, but none of them please me.
Maybe am I doing something wrong in my approach? I am a little bit confused about the Repository and DAO pattern (I read anything and the very opposite about that difference on the internet).
You have two options:
initialize new dbcontext for each operation and dispose it when operation is ended:
public abstract class GenericDao<TEntity, TDomain, TDbContext> : IGenericDao<TDomain>
where TDbContext : DbContext, new()
where TEntity : class
where TDomain : class
{
protected Func<TDbContext> _contextFactory;
public GenericDao(Func<TDbContext> contextFactory)
{
_contextFactory = contextFactory;
}
public TDomain Create()
{
using(var context = _contextFactory())
{
return context.Set<TEntity>().Create();
}
}
public IList<TDomain> GetAll()
{
using(var context = _contextFactory())
{
return context.Set<TEntity>().ToList()
.Select(entity => this.ToDomain(entity)).ToList();
}
}
public void Update(TDomain domain)
{
using(var context = _contextFactory())
{
var entity = this.ToEntity(domain);
context.Attach(entity);
var entry = this._context.Entry(entity);
entry.State = EntityState.Modified;
context.SaveChanges();
}
}
public void Remove(TDomain domain)
{
using(var context = _contextFactory())
{
var entity = this.ToEntity(domain);
context.Attach(entity);
context.Set<TEntity>.Remove(entity);
context.SaveChanges();
}
}
protected abstract TDomain ToDomain(TEntity entity);
protected abstract TEntity ToEntity(TDomain domain);
}
or you can try to find entity in your instance of dbcontext using property Local of DbSet:
var contextEntity = context.Set<TEntity>().Local
.Where(c=>c.Id == entity.Id).FirstOrDefault();
You seem to be getting stuck coding to an implementation within your abstraction. If you injected an interface to your generic rather than a concrete type (like EF) then your GenericDao becomes much more flexible. You can inject whatever implementation you choose providing it implements the required interface. In your case, WCF, File, Whatever. For example;
protected IDbContext _context;
public GenericDao(IDbContext dbContext)
{
this._context = dbContext;
}
public void Remove(TDomain domain)
{
_context.Remove(this.ToEntity(domain));
}
//abstraction
public interface IDbContext
{
void Remove(Entity entity);
}
//EF Implementation
public MyEfClass : IDbContext
{
public void Remove(Entity entity)
{
//code to remove for EF example
context.Attach(entity);
context.State = EntityState.Modified;
context.Set<TEntity>.Remove(entity);
context.SaveChanges();
}
}
//WCF Implementation
public MyWCFClass : IDbContext
{
public void Remove(Entity entity)
{
//Wcf implementation here
}
}
//File example
public FileWriter : IDbContext
{
public void Remove(Entity entity)
{
LoadFile();
FindEntry(entity);
WriteFile(entity);
SaveFile();
}
public void LoadFile()
{
//use app settings for file directory
}
}
I'm trying to use Simple Injector to create my repository and use it in the Business logic layer ( also i want to use PerWebRequest method ) .
In the DAL layer i have :
public interface IRepository<T> where T : class
{
void Add(T entity);
void Delete(T entity);
void Delete(int id);
void Update(T entity);
T GetById(int Id);
IQueryable<T> All();
IEnumerable<T> Find(Func<T, bool> predicate);
}
and :
public class EFRepository<T> : IRepository<T>, IDisposable where T : class
{
#region Members
protected DbContext Context { get; set; }
protected DbSet<T> DbSet { get; set; }
#endregion
#region Constructors
public EFRepository(DbContext dbContext)
{
if (dbContext == null)
throw new ArgumentNullException("dbContext");
Context = dbContext;
DbSet = Context.Set<T>();
}
and my context :
public class PASContext : DbContext, IDbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<User> Users { get; set; }
public PASContext()
: base("PostAndSell")
{ }
}
As you can see EFRepository has only one constructor that takes one argument - this is because i want to use Simple Injector to create an instance of the context and pass it to the repository while it is created .
In the BLL i have a class ProductBLL and i want to get all products in that class (with some GetAll method) from the database and pass it, lets say to HomeController .
I really need someone to talk me through this .
I started by installing the right packages from the nuger (Simple Injector and Simple Injector ASP.NET Integration)
also in my global.asax.cs file, under Application_Start() function I`ve added :
var container = new SimpleInjector.Container();
container.RegisterPerWebRequest<IRepository<Product>, EFRepository<Product>>();
but where do i create the Context instance ? and how can i access it in the business layer ?
Since you will probably have many IReposotory<T> implementations (for Product, Customer, Employee, etc), it's better make a single open generic registration for IRepository<T> like this:
container.Register(typeof(IRepository<>), typeof(EFRepository<>), Lifestyle.Scoped);
Where the scoped lifestyle is defined as:
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
This registration ensures that Simple Injector will return a EFRepository<Product>, every time a IRepository<Product> is requested, an EFRepository<Customer> for IRepository<Customer>, and so on, and so on.
Since you want the same DbContext instance to be used over all repositories within the same request, you should also register the DbContext with the scoped Lifestyle:
container.Register<DbContext, PASContext>(Lifestyle.Scoped);
In the BLL i have a class ProductBLL and i want to get all products
from the database and pass it to, lets say HomeController
In that scenario, this ProductBLL seems like a useless abstraction to me. If all it does is passing data through, you can as easily let your HomeController depend on IRepository<Product> directly.