need you help implementing UnitOfWork for my business layer.
Want to wrap multiple different business service calls into a single transaction.
Let's assume I use Entity Framework as my repository layer and I have an additional business layer for validation and other business rules. In this example just very very simple.
public class MyDbContext
{
public DbSet<User> Users;
public DbSet<Contract> Contracts;
}
public class UserService
{
public UserService(MyDbContext dbContext)
{
_dbContext = dbContext;
}
public void AddUser(User user)
{
_dbContext.Users.Add(user);
_dbContext.SaveChanges();
}
}
public class ContractService
{
public ContractService(MyDbContext dbContext)
{
_dbContext = dbContext;
}
public void AddContract(Contract contract)
{
_dbContext.Contracts.Add(contract);
_dbContext.SaveChanges();
}
}
In my controller:
userService.AddUser(user);
contractService.AddContract(contract);
... The add user calls already save changes but i want to save changes after add contract.
So can I do the following?? Or is this somehow bad design?!
Create UnitOfWork class:
public class UnitOfWork
{
public UnitOfWork(MyDbContext dbContext)
{
_dbContext = dbContext;
}
public MyDbContext DbContext => _dbContext;
public void SaveChanges()
{
_dbContext.SaveChanges();
}
}
Change my services to:
public class UserService
{
public UserService(UnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public void AddUser(User user)
{
_unitOfWork.DbContext.Users.Add(user);
}
}
public class ContractService
{
public ContractService(UnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public void AddContract(Contract contract)
{
_unitOfWork.DbContext.Contracts.Add(contract);
}
}
And then in my controller I do:
userService.AddUser(user);
contractService.AddContract(contract);
unitOfWork.SaveChanges();
Is this a valid approach?! Really need your help and thoughts on this...
Thanks!!!!
Your 'UnitOfWork' should contain methods that reflect your use cases. So I would have a method like 'CreateContract' which actually adds the 'user' and 'contract' and commits the transaction and just call this method from the controller.
public void CreateContract(User user,Contract contract)
{
this.dbContext.Users.Add(user);
this.dbContext.Contracts.Add(contract);
this.dbContext.SaveChanges();
}
This way you can encapsulate any transactional code within this method. Ex - if adding a user and contract are not simply EF calls but calls to different services, you can have a distributed transaction or other code to rollback the transaction.
Related
I have a Web API web service that uses EF for database operations and Unity for dependency injection. I have multiple databases with different names but the same schema. There's one database per retail store. When the user logs in, depending on his privileges, he can select which store he wants to work with. This is a challenge using dependency injection because I have to change the database after a repository has been injected. I have something that works but am not sure if it's the best approach.
My specific questions are:
Is this a good approach for this problem? I've seen other questions that mention changing the connection string at run time, but I think I'd either have to have a connection string per store in my Web.Config or build the connection string dynamically somehow.
Do I need the Dispose logic in my factory? If I were injecting a repository directly I know I wouldn't need it. Since I'm generating the repo from an injected factory, can I trust Unity to dispose of the repo and close the db connections at some point? Should I use using statements around the generated repos instead?
Some questions I looked at while trying to solve this problem are this one, this one, and this one. However, none of them directly accomplish what I'm trying to do. Below is my current solution.
This is my repository and its interface. I've left out some of the methods for brevity:
IGenericRepository
public interface IGenericRepository<T> where T: class
{
IQueryable<T> Get();
void ChangeDatabase(string database);
void Update(T entityToUpdate);
void Save();
}
GenericRepository
public class GenericRepository<TDbSet, TDbContext> :
IGenericRepository<TDbSet> where TDbSet : class
where TDbContext : DbContext, new()
{
internal DbContext Context;
internal DbSet<TDbSet> DbSet;
public GenericRepository() : this(new TDbContext())
{
}
public GenericRepository(TDbContext context)
{
Context = context;
DbSet = Context.Set<TDbSet>();
}
public virtual IQueryable<TDbSet> Get()
{
return DbSet;
}
public void ChangeDatabase(string database)
{
var dbConnection = Context.Database.Connection;
if (database == null || dbConnection.Database == database)
return;
if (dbConnection.State == ConnectionState.Closed)
{
dbConnection.Open();
}
Context.Database.Connection.ChangeDatabase(database);
}
public virtual void Update(TDbSet entityToUpdate)
{
DbSet.Attach(entityToUpdate);
Context.Entry(entityToUpdate).State = EntityState.Modified;
}
public virtual void Save()
{
Context.SaveChanges();
}
}
In order to use dependency injection I'm injecting a repository factory to which I can pass a database name. The factory creates a repository with the connection string's default database, changes the database to the one specified, and returns the repository.
IRepositoryFactory
public interface IRepositoryFactory
{
IGenericRepository<TDbSet> GetRepository<TDbSet>(string dbName) where TDbSet : class;
}
StoreEntitiesFactory
public class StoreEntitiesFactory : IRepositoryFactory
{
private bool _disposed;
readonly StoreEntities _context;
public StoreEntitiesFactory()
{
_context = new StoreEntities();
}
public IGenericRepository<TDbSet> GetRepository<TDbSet>(string dbName) where TDbSet : class
{
var repo = new GenericRepository<TDbSet, StoreEntities>(_context);
repo.ChangeDatabase(dbName);
return repo;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
_context.Dispose();
}
_disposed = true;
}
~StoreEntitiesFactory()
{
Dispose(false);
}
}
This is how I inject the repository factory in my WebApiConfig file:
WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
var container = new UnityContainer();
container.RegisterType<IRepositoryFactory, StoreEntitiesFactory>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
}
}
Finally, this is how I would use the factory in my controller:
StoreController
public class StoreController : ApiController
{
private readonly IRepositoryFactory _storeEntitiesRepoFactory;
public StoreController(IRepositoryFactory storeEntitiesRepoFactory)
{
_storeEntitiesRepoFactory = storeEntitiesRepoFactory;
}
[HttpGet]
public IHttpActionResult Get()
{
var dbName = getStoreDbName(storeNumberWeGotFromSomewhere);
try
{
var employeeRepo = _storeEntitiesRepoFactory.GetRepository<Employee>(dbName);
var inventoryRepo = _storeEntitiesRepoFactory.GetRepository<Inventory>(dbName);
var employees = employeeRepo.Get().ToList();
var inventory = inventoryRepo.Get().ToList();
}
catch (Exception ex)
{
return InternalServerError();
}
}
}
I think you probably want your IRepositoryFactory implementations to return the same repository for the same dbName. As it is written now, calling StoreEntitesFactory.GetRepository with two different dbName parameters will cause problems since it gives the same instance of StoreEntites to every repository.
To illustrate...
public class DemonstrationController
{
private readonly IRepositoryFactory _storeEntitiesRepoFactory;
public DemonstrationController(IRepositoryFactory storeEntitiesRepoFactory)
{
_storeEntitiesRepoFactory = storeEntitiesRepoFactory;
}
[HttpGet]
public IHttpActionResult Get()
{
var empRepo1 = _storeEntitiesRepoFactory.GetRepository("DB1");
var empRepo2 = _storeEntitiesRepoFactory.GetRepository("DB2");
// After the second line, empRepo1 is connected to "DB2" since both repositories are referencing the same
// instance of StoreEntities
}
}
If you changed StoreEntitiesFactory to return the same repository based on the given parameter, this would solve that problem.
public class StoreEntitiesFactory : IRepositoryFactory
{
private bool _disposed;
private Dictionary<string, StoreEntities> _contextLookup;
public StoreEntitiesFactory()
{
_contextLookup = new Dictionary<string, StoreEntities>();
}
public IGenericRepository<TDbSet> GetRepository<TDbSet>(string dbName) where TDbSet : class
{
if (!_contextLookup.TryGetValue(dbName, out StoreEntities context))
{
context = new StoreEntities();
// You would set up the database here instead of in the Repository, and you could eliminate
// the ChangeDatabase function.
_contextLookup.Add(dbName, context);
}
return new GenericRepository<TDbSet, StoreEntities>(context);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize();
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
foreach (var context in _contextLookup.Values)
{
context.Dispose();
}
}
_disposed = true;
}
}
}
As for the second question, you would need the dispose logic in the factory since it owns the instances of StoreEntities being created. No need to use using statements around the repositories it creates, just let Unity dispose of the factory.
I'd recommend you to use a design pattern called a Strategy Pattern to solve this problem.
This pattern allows you to change between two or more strategies on runtime.
Reference: https://en.wikipedia.org/wiki/Strategy_pattern
For the injection, I'd suggest you register two concrete classes on the Unity, one for each DB Connection and call the Resolve method for the one you need passing the string to instantiate the DB.
IUnityContainer container = new UnityContainer();
container.RegisterType<ICar, BMW>();
container.RegisterType<ICar, Audi>("LuxuryCar");
ICar bmw = container.Resolve<ICar>(); // returns the BMW object
ICar audi = container.Resolve<ICar>("LuxuryCar"); // returns the Audi object
Reference: https://www.tutorialsteacher.com/ioc/register-and-resolve-in-unity-container
About the Dispose, you can config all of these concrete classes to the DBs as Singletons, and let all the connections opened, but you will need to verify if this is possible to your application.
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.
For every page request, I need to get some current user permissions data from the database and then use this information several times in the logic
(which is made of several objects)
I want to get data from the database once per request, and reuse it where needed by injecting it.
Is the following the best way to do this?
1) define a object like this
class ApplicationUser : IApplicationUserProvider
{
private UserPermissions _userPermissions;
...
public ApplicationUser(IDatabase userService)
{
_userPermissions = userService.GetUserPermission(); // this would executed for every request once
}
UserRoles GetRoles()
{
return _userPermissions;
}
}
2) define the ioc something like this
var container1 = new Container(c =>
{
c.For<IDatabase>().Use<Database>();
c.For<IApplicationUser>().Use<ApplicationUser >();
c.For<IApplicationLogic1>().Use<ApplicationLogic1>(); // this has IApplicationUser in ctor
c.For<IApplicationLogic2>().Use<ApplicationLogic2>(); // this has IApplicationUser in ctor
});
3) the controller would be
void PageController(IApplicationLogic1 l1)
{
l1.Process();
l2.Process();
}
The UserPermissions information is runtime data, and as explained here, runtime data should not be injected or resolved during construction of the object graphs.
Instead, the call to userService.GetUserPermission() should be moved out of the constructor. For instance by delaying the call by using a Lazy<T>:
class ApplicationUser : IApplicationUserProvider
{
private Lazy<UserPermissions> _userPermissions;
public ApplicationUser(IDatabase userService) {
_userPermissions = new Lazy<UserPermissions>(userService.GetUserPermission);
}
UserRoles GetRoles() {
return _userPermissions.Value.GetRoles();
}
}
Another option is to define a decorator on IDatabase that will implement the caching:
public class PerRequestCacheDatabaseDecorator : IDatabase
{
private IDatabase _decoratee;
public PerRequestCacheDatabaseDecorator(IDatabase decoratee) {
_decoratee = decoratee;
}
public UserPermissions GetUserPermission() {
var items = HttpContext.Current.Items;
if (items["permissions"] == null)
items["permissions"] = _decoratee.GetUserPermission();
return (UserPermissions)items["permissions"];
}
}
By wrapping the real database inside the PerRequestCacheDatabaseDecorator, you can simplify the ApplicationUser to the following:
class ApplicationUser : IApplicationUserProvider
{
private IDatabase _userService;
public ApplicationUser(IDatabase userService) {
_userService = userService;
}
public UserRoles GetRoles() {
return _userService.GetUserPermission().GetRoles();
}
}
Now neither the ApplicationUser nor the Database class are concerned with this performance optimization, which is a good thing. The decorator allows us to plugin this performance optimization without having to change any of the existing classes.
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 have a View that is bound to a NewUserViewModel which is posted to this method of the controller.
[HttpPost]
public ActionResult NewUser(NewUserViewModel newUser)
{
var user = new User();
user.Id = newUser.Id;
user.Email = newUser.Email;
//more mapping hidden for brevity
//here is where the trouble starts
_userService.AddNewUser(user);
return RedirectToAction("Users");
}
The _userService is in a private field that is instantiated in the controllers constructor like this
private IUserService _userService;
public ControllerName()
{
_userService = new UserService();
}
The AddNewUser method on the _userService looks like this.
public void AddNewUser(User newUser)
{
using (var uow = new UnitOfWorkUser(new Context()))
{
using (var _userRepo = new UserRepository(uow))
{
_userRepo.InsertOrUpdate(newUser);
uow.Save();
}
}
}
The constructor of the UserRepository looks like this.
private Context _context;
public UserRepository(UnitOfWorkUser unitOfWork)
{
_context = unitOfWork.Context;
}
and the unitOfWorkLooks like this.
public class UnitOfWorkUser :IDisposable, IUnitOfWork
{
private readonly Context _context;
public UnitOfWorkUser(Context context = null)
{
_context = context ?? new Context();
}
public int Save()
{
return _context.SaveChanges();
}
internal Context Context
{
get { return _context; }
}
public void Dispose()
{
_context.Dispose();
}
}
And the InsertOrUpdate Method on the _userRepo looks like this.
public virtual void InsertOrUpdate(User user)
{
if (user.Id == default(int))
{
_context.Users.Add(user);
}
else
{
_context.Entry(user).State = System.Data.EntityState.Modified;
}
}
When I get to the
_context.Users.Add(user);
in the method above I get this error
An entity object cannot be referenced by multiple instances of IEntityChangeTracker.
I thought by passing in the Context with the UnitOfWork Object in the constructor of the UserRepository I was going to be avoiding these errors.
What am I doing wrong?
There is a better approach to use UOW in asp.net mvc, you dont consider many aspects of entity life time in context, so I suggest reading this article
This looks very wrong to me. The purpose of unit work pattern is to consolidate all your "work" in one object. There is several issue with the following code:
Looks like you are disposing the DBContext Twice
Since you only need dbcontext, you shouldn't only pass dbcontext to the repository instead of UOW object
You might want to have a internal reference to the UserRepository. It should be used to group your Repositories and ensure they all share the same EF context instance. A sample will look like UnitOfWorkUser.UserRepo.Save(newUser)
using (var uow = new UnitOfWorkUser(new Context()))
{
using (var _userRepo = new UserRepository(uow))
{
_userRepo.InsertOrUpdate(newUser);
uow.Save();
}
}
Here is an example on how you use UOW,
http://www.mattdurrant.com/ef-code-first-with-the-repository-and-unit-of-work-patterns/