I have followed this tutorial.
I got to a stage of calling a repository using _unitOfWork.XYZRepository.Get(), now to take it further I want to write an interface for my UnitOfWork class and inject it to my controller.
I am not sure whether I need write interface for GenericRepository or UnitofWork class or both.
Can some one guide me in this as to what needs to be done to instantiate a repository with interface instead of private readonly UnitOfWork _unitOfWork = new UnitOfWork(); as shown in the link above.
Modify your repository constructor to accept a unit of work, via its interface:
public MyRepository(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
Then you instantiate your repository, passing the appropriate unit of work in via the constructor. Alternatively, wire-up your IoC container of choice and let it do the heavy lifting.
Here's a nice tutorial on using Castle Windsor with ASP.NET MVC.
I have used Autofac for this purpose. In my Global.asax.cs file
var builder = new ContainerBuilder();
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerApiRequest();
builder.RegisterAssemblyTypes(typeof (LocationTypesRepository).Assembly).Where(
type => type.Name.EndsWith("Repository")).AsImplementedInterfaces();
and then in my controller
public class LocationTypesController : ApiController
{
private readonly ILocationRepository _locationRepository;
private readonly IUnitOfWork _unitOfWork;
private readonly IAuthenticatedUser _user;
public LocationTypesController(ILocationRepository locationRepository,
IUnitOfWork unitOfWork,
IAuthenticatedUser user)
{
if (locationRepository == null)
throw new ArgumentNullException("locationRepository");
if (unitOfWork == null)
throw new ArgumentNullException("unitOfWork");
if (user == null)
throw new ArgumentNullException("user");
_locationRepository = locationRepository;
_unitOfWork = unitOfWork;
_user = user;
}
public IEnumerable<LocationType> Get()
{
try
{
IEnumerable<Location> locations = _locationRepository.GetAllAuthorizedLocations(_user.UserName);
_unitOfWork.Commit();
return locations.Select(location => location.LocationType).Distinct().OrderBy(location => location.LocationTypeId);
}
catch (Exception)
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.BadRequest));
}
}
Essentially leveraging a DI framework and placing the interfaces as parameters to your repositories (or in my case a WebApi controller)
Based on suggestions I have made following changes...
public interface IGenericRepository<T> where T : class
{
IQueryable<T> Get();
IQueryable<T> FindBy(Expression<Func<T, bool>> predicate);
void Insert(T entity);
void Delete(T entity);
void Update(T entity);
void Save();
T GetByID(Object id);
}
public class GenericRepository<C, T> : IGenericRepository<T>
where T : class
where C : EFDbContext, new()
{
private C _entities = new C();
public C Context
{
get { return _entities; }
set { _entities = value; }
}
public virtual IQueryable<T> Get()
{
IQueryable<T> query = _entities.Set<T>();
return query;
}
public virtual T GetByID(object id)
{
return Context.Set<T>().Find(id);
}
}
//NinjectControllerFactory
private void AddBindings()
{
_ninjectKernel.Bind<IGenericRepository<Product>>().To<GenericRepository<EFDbContext, Product>>();
}
//Controller
[Inject]
public IGenericRepository<Product> ProductRepo;
public ProductController(IGenericRepository<Product> ProductRepository )
{
ProductRepo= ProductRepository ;
}
//Inside Action
model.Products = ProductRepo.Get();
Everything works now... Thanks for the help...
Related
I am learning to code in c# and I am developing an API application. My GET method works but I have issues with my DELETE, it returns a success code(200) but it does not delete from my database which is connected to my application. I am using the unit of work and repository patterns and my code is as follows:
Controller code:
private readonly IOrderService _orderService;
public OrdersController(IOrderService orderService)
{
_orderService = orderService;
}
[HttpDelete("{id}")]
public async Task<ActionResult> RemoveOrder(int id)
{
try
{
await _orderService.Delete(id);
return StatusCode(200);
}
catch (Exception ex)
{
return StatusCode(500);
}
}
Service Interface
public interface IOrderService
{
Task<Order> Get(int id);
Task Add(Order order);
Task Delete(int id);
Task Update(int id, Order order);
Task<IEnumerable<Order>> GetAllOrdersAsync();
Task<IEnumerable<OrderDTO>> GetOrdersToCityAsync(string cityName);
Task<OrderDTO> GetEmployeeOrdersToCountryAsync
(
string countryName, string employeeLastName
);
}
Service class:
public class OrderService : IOrderService
{
private readonly IUnitOfWork _unitOfWork;
public OrderService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public async Task Delete(int id)
{
try
{
var order = await _unitOfWork.OrderRepository.Get(id);
_unitOfWork.OrderRepository.Delete(order);
await _unitOfWork.CommitAsync();
}
catch (Exception e)
{
await _unitOfWork.RollbackAsync();
throw;
}
}
}
Unit of work class:
public class UnitOfWork : IUnitOfWork
{
private readonly NorthwindContext _db;
private List<object> _customRepositories = new List<object>();
private IProductRepository _productRepository;
private IOrderRepository _orderRepository;
public UnitOfWork(
NorthwindContext db,
IProductRepository ProductRepository,
IOrderRepository orderRepository
)
{
_db = db;
_productRepository = ProductRepository;
_orderRepository = orderRepository;
}
uow interface:
public interface IUnitOfWork
{
IProductRepository ProductRepository { get; }
IOrderRepository OrderRepository { get; }
Task CommitAsync();
Task RollbackAsync();
}
Order repository interface which extends my genericRepository:
public interface IOrderRepository : IGenericRepository<Order>
{
Task<IEnumerable<OrderDTO>> GetOrdersToCityAsync(string cityName);
Task<OrderDTO> GetEmployeeOrdersToCountryAsync
(
string countryName, string employeeLastName
);
}
Order repository:
public class OrderRepository : GenericRepository<Order>, IOrderRepository
{
private readonly NorthwindContext _northwindContext;
public OrderRepository(NorthwindContext db) : base(db)
{
_northwindContext = db;
}
generic repository:
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
protected readonly NorthwindContext _db;
public GenericRepository(NorthwindContext db)
{
_db = db;
}
public void Delete(T entity)
{
_db.Set<T>().Remove(entity);
}
Please ignore if the curly braces are not closed properly, in my application they are.
Please check the following items:
Unit of work implementation calls SaveChanges() on CommitAsync implementation.
NorthwindContext object instance passed to repositories is the same instance as the one injected into UnitOfWork class. Otherwise you'll be working in different transactions.
You could delete an entry from database while using the following code.
[HttpDelete{"id"}]
Public async<Task<ActionResult>> DeleteItem (int id)
{ try{
Var itemToDelete = await UnitofWork.OrderRepository.GetAsync(id);
If (Id!= null) {
await Orderservice.Delete(itemToDelete);
var result = await UnitofWork.SaveChangesAsync();
If (result) return StatusCode(200);
Else return BadRequest();
return ok(itemToDelete);
} catch(exception ex) {
Throw new Error("Problem while deleting!");
}
Return BadRequest();
}
}
Just check if the item you would want ro delete is null or not. Then attempt to delete it from database. Hoping it would give you an idea.
I have a WindowsForm Project With this design :
DAL(GenericRepository => UnitOfWork) => BLL(Service) => UI
And use EntityFramWork, Interface, GenericRepository, Dependency Injection
My Code in Repository(DAL) :
public class Repository : RepositoryBase, IDisposable, IRepository where T : class
{
private readonly DbSet dbSet;
private bool disposed = false;
public Repository(GlobalERPEntities dbContext)
{
DBContext = dbContext;
dbSet = DBContext.Set();
}
public virtual IEnumerable GetAll()
{
return dbSet.ToList();
}
}
UnitOfWork(DAL) :
public class UnitOfWork : RepositoryBase, IUnitOfWork, IDisposable
{
private Dictionaryobject> repositories;
private bool disposed = false;
public UnitOfWork(GlobalERPEntities dbContext)
{
DBContext = dbContext;
}
public IRepository Repository() where T : class
{
if (repositories == null)
{
repositories = new Dictionaryobject>();
}
if (repositories.Keys.Contains(typeof(T)) == true)
{
return repositories[typeof(T)] as Repository;
}
Repository repo = new Repository(DBContext);
repositories.Add(typeof(T), repo);
return repo;
}
Service(BLL) :
public class Service_HR_Person : IService_HR_Person , IDisposable
{
private readonly IUnitOfWork UnitOfWork;
public Service_HR_Person(IUnitOfWork unitOfWork)
{
UnitOfWork = unitOfWork;
}
public virtual IEnumerable GetAll()
{
return UnitOfWork.Repository().GetAll().ToList();
}
MyForm(UI) :
using (Service_HR_Person srvPerson = new Service_HR_Person())
{
srvPerson.Delete(base.rowid);
try
{
srvPerson.Save();
MessageManager.Show(Enums.MessageBoxType.InformationTransactionSuccessfully);
}
catch (Exception ex)
{
MessageManager.Show(ErrorManager.ProccessException(ex), Enums.MessageBoxType.Error);
}
}
Iknow should not use DAL Layer in UI layer and BLL is between DAL and UI
but i have error in ui
using (Service_HR_Person srvPerson = new Service_HR_Person())
"new Service_HR_Person()" say need an arguman in () that is unitofwork but we should not use unitofwork in UI
i read some article and sample that use IOC , ninject ,bootstraper and ... but i cant write true code
How To use Ninject or IOC?
please help me with code
thankyou
add a new project to solution with name "Configure"
add castle.windsor from NuGet to all project
add a class to this project with name "Bootstrapper" and write this code
public static WindsorContainer Container = null;
public static void WireUp()
{
Container = new WindsorContainer();
Container.Register(Component.For<GlobalERPEntities>());
Container.Register(Component.For<IUnitOfWork>().ImplementedBy<UnitOfWork>());
Container.Register(Component.For<IService_HR_Person>().ImplementedBy<Service_HR_Person>());
}
and edit your code in UI
using (Service_HR_Person srvPerson = Bootstrapper.Container.Resolve<Service_HR_Person>())
{
srvPerson.Delete(base.rowid);
try
{
srvPerson.Save();
RemoveRow();
MessageManager.Show(Enums.MessageBoxType.InformationTransactionSuccessfully);
}
catch (Exception ex)
{
MessageManager.Show(ErrorManager.ProccessException(ex), Enums.MessageBoxType.Error);
}
}
this line
using (Service_HR_Person srvPerson = Bootstrapper.Container.Resolve<Service_HR_Person>())
and edit Program.cs with this code
static void Main(string[] argss)
{
Bootstrapper.WireUp();
this is work corectly
I am following the Repository pattern and implementing UnitOfWork.
Here is the issue:
Within the EmployeeController, there is a post call titled AddEmployee(). This action method gets the appropriate data and the result comes back successful, but the data is not getting saved to the database. The action method is also calling the SaveEmployee() method, which should in theory save the data.
Git Repo: https://bitbucket.org/ChaseHardin/myapp
Question: Why isn't the UnitOfWork saving the database changes?
Controller:
[HttpPost]
public HttpResponseMessage AddEmployee([FromBody]Employee employee)
{
if (ModelState.IsValid)
{
_employeeService.AddEmployee(employee);
_employeeService.SaveEmployee();
return new HttpResponseMessage(HttpStatusCode.OK);
}
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
Service:
public class EmployeeService : IEmployeeService
{
private readonly IEmployeeRepository _employeeRepository;
private readonly IUnitOfWork _unitOfWork;
public EmployeeService(IUnitOfWork unitOfWork, IEmployeeRepository employeeRepository)
{
_unitOfWork = unitOfWork;
_employeeRepository = employeeRepository;
}
public Employee GetEmployee(int id)
{
return _employeeRepository.GetById(id);
}
public void SaveEmployee()
{
_unitOfWork.Commit();
}
public void AddEmployee(Employee employee)
{
_employeeRepository.Add(employee);
}
}
public interface IEmployeeService
{
Employee GetEmployee(int id);
void SaveEmployee();
void AddEmployee(Employee employee);
}
UnitOfWork
public class UnitOfWork : IUnitOfWork
{
private readonly IDbFactory dbFactory;
private MyAppEntities dbContext;
public UnitOfWork(IDbFactory dbFactory)
{
this.dbFactory = dbFactory;
}
public MyAppEntities DbContext
{
get { return dbContext ?? (dbContext = dbFactory.Init()); }
}
public void Commit()
{
DbContext.Commit();
}
}
public interface IUnitOfWork
{
void Commit();
}
MyAppEntities:
public class MyAppEntities : DbContext
{
public MyAppEntities() : base("MyAppEntities") { }
public DbSet<Employee> Employees { get; set; }
public virtual void Commit()
{
SaveChanges();
}
}
EmployeeRepository
public class EmployeeService : IEmployeeService
{
private readonly IEmployeeRepository _employeeRepository;
private readonly IUnitOfWork _unitOfWork;
public EmployeeService(IUnitOfWork unitOfWork, IEmployeeRepository employeeRepository)
{
_unitOfWork = unitOfWork;
_employeeRepository = employeeRepository;
}
public Employee GetEmployee(int id)
{
return _employeeRepository.GetById(id);
}
public void SaveEmployee()
{
_unitOfWork.Commit();
}
public void AddEmployee(Employee employee)
{
_employeeRepository.Add(employee);
}
}
public interface IEmployeeService
{
Employee GetEmployee(int id);
void SaveEmployee();
void AddEmployee(Employee employee);
}
Base Repo
public abstract class BaseRepository <T> where T : class
{
private MyAppEntities _dataContext;
private readonly IDbSet<T> _dbSet;
protected IDbFactory DbFactory { get; private set; }
protected MyAppEntities DbContext
{
get { return _dataContext ?? (_dataContext = DbFactory.Init()); }
}
protected BaseRepository(IDbFactory dbFactory)
{
DbFactory = dbFactory;
_dbSet = DbContext.Set<T>();
}
#region Implementation
public virtual void Add(T entity)
{
_dbSet.Add(entity);
}
public virtual void Update(T entity)
{
_dbSet.Attach(entity);
_dataContext.Entry(entity).State = EntityState.Modified;
}
public virtual void Delete(T entity)
{
_dbSet.Remove(entity);
}
public virtual void Delete(Expression<Func<T, bool>> where)
{
IEnumerable<T> objects = _dbSet.Where<T>(where).AsEnumerable();
foreach (T obj in objects)
_dbSet.Remove(obj);
}
public virtual T GetById(int id)
{
return _dbSet.Find(id);
}
public virtual IEnumerable<T> GetAll()
{
return _dbSet.ToList();
}
public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where)
{
return _dbSet.Where(where).ToList();
}
public T Get(Expression<Func<T, bool>> where)
{
return _dbSet.Where(where).FirstOrDefault<T>();
}
#endregion
}
public interface IBaseRepository<T> where T : class
{
void Add(T entity);
void Update(T entity);
void Delete(T entity);
void Delete(Expression<Func<T, bool>> where);
T GetById(int id);
T Get(Expression<Func<T, bool>> where);
IEnumerable<T> GetAll();
IEnumerable<T> GetMany(Expression<Func<T, bool>> where);
}
The issue is your IOC scope. In App_Start you are binding your objects with the default Transient Scope. This is causing multiple contexts to be created, and you are adding the employee in one context and calling SaveChanges() on another.
Update your Ninject bindings to use InSingletonScope() or InRequestScope().
As #TimS mentioned it is totally about how you register your services at application start. I had same problem with similar pattern while I was using autofac instead of Ninject.
With autofac if you don't choose lifetime scope it is Instance Per Dependency scope as default. By this scope for each request an instance of registered object returns; this cause multiple context at same scope and when you commit your changes by unitofwork instance it just commit wrong instance of Context. To avoiding this you have to use single instance scope or better for this case Instance Per Lifetime Scope
This scope applies to nested lifetimes. A component with per-lifetime
scope will have at most a single instance per nested lifetime scope.
This is useful for objects specific to a single unit of work that may
need to nest additional logical units of work. Each nested lifetime
scope will get a new instance of the registered dependency.
var builder = new ContainerBuilder();
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerLifetimeScope();
builder.RegisterType<DbFactory>().As<IDbFactory>().InstancePerLifetimeScope();
I am still learning UnitOfWork pattern and I am not comfortable with this yet. I found many examples but nothing is clear enough for my problem.
I want use UnitOfWork with Ado.Net.
I have many repositories. I want call different methods from different repositories in same transaction using Unit of work.
For example a have this 2 repositories.
public class FirstRepository : IFirstRepository
{
private readonly ILogger logger;
private readonly IImportConfiguration configuration;
public FirstRepository(ILogger logger, IImportConfiguration configuration)
{
this.logger = logger;
this.configuration = configuration;
}
public int Save()
{
//Save to DB with Ado.Net
return 1;
}
}
public class SecondRepository : ISecondRepository
{
private readonly ILogger logger;
private readonly IImportConfiguration configuration;
public SecondRepository(ILogger logger, IImportConfiguration configuration)
{
this.logger = logger;
this.configuration = configuration;
}
public int Update()
{
//Update in DB with Ado.Net
return 1;
}
}
I want call functions Save() and Update() in same transaction.
using (var uow = UnitOfWorkFactory.Create())
{
firstRepository.Save();
secondRepository.Update();
_unitOfWork.SaveChanges();
}
Problem is how to use same UnitOfWork in both repositories ? Only thing I can see is add additional parameter to functions
//in first repository
Save(IUnitOfWork uow)
//in second repository
Update(IUnitOfWork uow)
//****************************
using (var uow = UnitOfWorkFactory.Create())
{
firstRepository.Save(uow);
secondRepository.Update(uow);
_unitOfWork.SaveChanges();
}
This is ugly solution, because i must have this parameter in all functions that work with DB.
I am using Dependency injection. ILogger and IImportConfiguration are injected with AutoFac. Maybe would be good to register all repositories in UnitOfWork? But how to do that? I cant have just one instance injected in all repositories.
Any idea?
public class UnitOfWork
{
public DbSet<Company> Companies { get; set; }
public int SaveChanges()
{
underlyingContext.SaveChanges();
}
}
public class UnitOfWorkFactory
{
public UnitOfWork Create()
{
// real creation logic
return new UnitOfWork();
}
}
public class CompanyRepository
{
private readonly UnitOfWork uow;
public CompanyRepository(UnitOfWork uow)
{
uow = uow;
}
public void Add(Company company)
{
uow.Companies.Add(company);
}
}
public class CompanyRepositoryFactory
{
public Create(UnitOfWork uow)
{
new CompanyRepository(uow);
}
}
Tying it all together:
var uow = new UnitOfWorkFactory().Create();
var companyRepository = new CompanyRepositoryFactory().Create(uow);
So to use DI, you need to create interfaces for all these.
The unit of work is based round some Data Layer connection, for example EF uses DbContext which you would use in the underlying UnitOfWork class.
Other things you can do is make IUnitOfWork (the interface) inherit IDisposable so you use the using().
To make it so you don't have a hundred repository classes (although not really a bad thing) you can make it Generic, so IRepository<T> and Repository<T>
So for a generic repo and unit of work using EF.
public class UnitOfWork : IUnitOfWork
{
ProjectDbContext context;
public UnitOfWork() {
context = new ProjectDbContext();
}
public IQueryable<T> Query<T>(Expression<Func<bool, t>> predicate)
{
return context.Set<T>().Where(predicate);
}
public void Add<T>(T entity)
{
context.Set<T>().Add(entity);
}
public int SaveChanges()
{
return context.SaveChanges();
}
public void Dispose()
{
context.Dispose();
}
}
public class UnitOfWorkFactory
{
Lazy<UnitOfWork> lazyUOW = new Lazy<UnitOfWork>(() => new UnitOfWork());
public UnitOfWork Create()
{
// having the DI initialise as Singleton isn't enough.
return lazyUOW.Value;
}
}
public class Repository<T> : IRepository<T>
{
private readonly IUnitOfWork uow;
public Repository(IUnitOfWork uow)
{
uow = uow;
}
public void Add(T entity)
{
uow.Add(entity);
}
public List<T> AllBySomePredicate(Expression<Func<bool, T>> predicate)
{
return uow.Query(predicate).ToList();
}
}
public class RepositoryFactory : IRepositoryFactory
{
public Create<T>(UnitOfWork uow)
{
new Repistory<T>(uow);
}
}
Usage:
public class CompanyController : Controller
{
private readonly IUnitOfWorkFactory uowFactory;
private readonly IRepositoryFactory repoFactory;
public CompanyController (
IUnitOfWorkFactory uowFactory,
IRepositoryFactory repoFactory)
{
uowFactory = uowFactory;
repoFactory = repoFactory;
}
public ActionResult Index()
{
using(var uow = uowFactory.Create())
{
var companyRepo = repoFactory.Create<Company>(uow);
return View(companyRepo.AllBySomePredicate(x => x.CompanyJoined == DateTime.Now.AddMonths(-2)));
}
}
}
Is there a way I can accomplish something like this:
var builder = new ContainerBuilder();
builder.Register(c => c.Resolve<DbContext>().Set<TEntity>()).As(IDbSet<TEntity>);
Sure, and there's even a pattern for that. It's called the repository pattern:
public interface IRepository<TEntity>
{
IQueryable<TEntity> GetAll();
TEntity GetById(Guid id);
}
public class EntityFrameworkRepository<TEntity> : IEntity<TEntity>
{
private readonly DbContext context;
public EntityFrameworkRepository(DbContext context) {
this.context = context;
}
public IQueryable<TEntity> GetAll() {
return this.context.Set<TEntity>();
}
public TEntity GetById(Guid id) {
var item = this.context.Set<TEntity>().Find(id);
if (item == null) throw new KeyNotFoundException(id.ToString());
return item;
}
}
You can register it as follows:
builder.RegisterGeneric(typeof(EntityFrameworkRepository<>)).As(typeof(IRepository<>));