I'm trying to test MVC actions, so i created IRepository and MockRepository
public class Repository : DbContext, IRepository
{
public IDbSet<TEntity> SomeEntities { get; set; }
}
public interface IRepository : IDisposable
{
IDbSet<TEntity> SomeEntities { get; set; }
int SaveChanges();
}
With Create and Delete actions it was simple, but stuck with Edit action :
private IRepository repository;
public ActionResult Edit(TEntity entity)
{
if (ModelState.IsValid)
{
repository.Entry(entity).State = EntityState.Modified;
repository.SaveChanges();
return RedirectToAction("Index");
}
return View(entity);
}
So i see two ways to solve this problem:
should i add to IRepository new method
DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
How i could do this? DbContext.Entry method returns very specific DbEntityEntry<TEntity> type?
or change the way i update entity? What is recommended way to do this?
I would normally abstract the functionality of EF more than you are, meaning my actions look the following.
private IRepository repository;
public ActionResult Edit(TEntity entity)
{
if (ModelState.IsValid)
{
repository.Update(entity);
repository.SaveChanges();
return RedirectToAction("Index");
}
return View(entity);
}
then you can easily make a mock repository and test that the desired functions are called.
Note: I normally also separate my entities from my models and manage my unit of work using an action filter, but that's not really related to this post.
Related
I have a Interface named IRepository and class named Repository to implement Repository pattern in C# MVC as
public interface IRepository<TEntity>
{
void Insert(TEntity entity);
void Delete(TEntity entity);
}
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
DbSet<TEntity> DbSet;
TestDBEntities dataContext;
public Repository(TestDBEntities dataContext)
{
this.dataContext = dataContext;
this.DbSet = dataContext.Set<TEntity>();
}
public void Insert(TEntity entity)
{
DbSet.Add(entity);
dataContext.SaveChanges();
}
public void Delete(TEntity entity)
{
DbSet.Remove(entity);
}
public IQueryable<TEntity> SearchFor(Expression<Func<TEntity, bool>> predicate)
{
return DbSet.Where(predicate);
}
}
and here is my controller:
public class HomeController : Controller
{
private IRepository<Tbl_EmpDetails> _EmpDetails;
public HomeController()
{
_EmpDetails = new Repository<Tbl_EmpDetails>(new TestDBEntities());
}
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(Tbl_EmpDetails empDetials)
{
_EmpDetails.Insert(empDetials);
return Redirect("/");
}
}
As per my idea in controller i should not have to use "new TestDBEntities()" because instance of EDMX will be create again and again when Insert,Update,Delete or any another function of controller will call and there will be no use of Repository. (TestDBEntity is object of my EDMX).
_EmpDetails = new Repository<Tbl_EmpDetails>(new TestDBEntities());
Tbl_EmpDetails is an table under EDMX.
Please suggest me what is the perfect way to implement repository structure according to my code and also if you have any other Suggestion to improve my code.
Thanks in advance.
This is how i structure my project.
Project.Web
-> Controllers
Project.Domain
-> Contracts
-> Services
Project.Data
-> Contracts
-> Repositories
So in my controller, only the service was exposed (so all the implementations are encapsulated). I used ninject to handle this dependencies.
public SomeController(IService service)
{
}
INSIDE MY DOMAIN PROJECT
An interface and a class that derived that interface was implemented. So basically, this only calls the repository project and other business logic should reside here.
The interface
public interface IService
{
IEnumerable<SomeClass> FindAll();
}
The implementation
public class Service : IService
{
private ISomeRepository _someRepository; // Exposed instance of my repo
public IEnumerable<SomeClass> FindAll()
{
return _someRepository.FindAll();
}
}
INSIDE MY DATA PROJECT
I also have two implementations one for the interface and another one for the class which implementing this interface.
The interface
public interface ISomeRepository
{
IEnumerable<Some> FindAll();
}
The implementation
public class SomeRepository : BaseRepository, ISomeRepository
{
public R(IUnitOfWork unitOfWork)
: base(unitOfWork)
{
}
public IEnumerable<SomeClass> FindAll()
{
return this.GetDbSet<SomeClass>();
}
}
If you wonder what is the use of BaseRepository and UnitOfWork, this will holds the context of our model (EDMX).
Base Repository
public class BaseRepository
{
protected IUnitOfWork UnitOfWork { get; set; }
protected MyEntities Context
{
get { return (MyEntities)this.UnitOfWork.Database; }
}
public BaseRepository(IUnitOfWork unitOfWork)
{
if (unitOfWork == null) throw new ArgumentNullException("unitOfWork");
this.UnitOfWork = unitOfWork;
}
protected virtual DbSet<TEntity> GetDbSet<TEntity>() where TEntity : class
{
return this.Context.Set<TEntity>();
}
protected virtual void SetEntityState(object entity, EntityState entityState)
{
this.Context.Entry(entity).State = entityState;
}
}
Unit Of Work
public class UnitOfWork : IUnitOfWork, IDisposable
{
public DbContext Database { get; private set; }
public UnitOfWork(DbContext dbContext)
{
Database = dbContext;
}
public void SaveChanges()
{
Database.SaveChanges();
}
public void Dispose()
{
Database.Dispose();
}
}
The IUnitOfWork interface
public interface IUnitOfWork
{
DbContext Database { get; }
/// <summary>
/// Saves changes to all objects that have changed within the unit of work.
/// </summary>
void SaveChanges();
}
So for this, we cater the issue of separation of concerns and each project serves it's true purpose
My app is layered in 4 layers:
Core: where I put some general and interface classes.
Model: where my code-first classes, and other related to domain, such as entity configurations and repositories etc.
Vm: where the view models live. Referencing Model.
Desktop: where the desktop app lives. Referencing Vm.
I have installed Entity Framework into Model, ViewModel and Desktop.
My question is: is it enough to install it into Model only? Why to repeat again?
[Edit]
Here is my implementation of Repository and UnitOfWrok (
IRepository and Repository will be on Core):
public interface IRepository<TEntity> where TEntity : class
{
TEntity Get(int id);
IEnumerable<TEntity> GetAll();
IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate);
TEntity SingleOrDefault(Expression<Func<TEntity, bool>> predicate);
void Add(TEntity entity);
void AddRange(IEnumerable<TEntity> entities);
void Remove(TEntity entity);
void RemoveRange(IEnumerable<TEntity> entities);
}
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
protected readonly DbContext Context;
public Repository(DbContext context)
{
Context = context;
}
public TEntity Get(int id)
{
return Context.Set<TEntity>().Find(id);
}
and so on...
}
Now, the new next interfaces and classed will be on Model
public interface ICountryRepository : IRepository<Country> {}
public class CountryRepository : Repository<Country>, ICountryRepository
{
public CountryRepository(CmsDbContext cmsDbContext)
: base(cmsDbContext) {}
}
interface IUnitOfWork : IDisposable
{
ICountryRepository CountryRepository { get; }
}
public class UnitOfWork : IUnitOfWork
{
private readonly CmsDbContext _context;
public UnitOfWork(CmsDbContext context)
{
_context = context;
CountryRepository = new CountryRepository(_context);
}
public ICountryRepository CountryRepository { get; private set; }
public int Commit()
{
return _context.SaveChanges();
}
public void Dispose()
{
_context.Dispose();
}
}
Now, in my ViewModel
private UnitOfWork Currentunitofwork;
Currentunitofwork = new UnitOfWork(new CmsDbContext());
I followed a description of a tutor in udemy.
Is this separation correct?
Move all repository (Entity framework) methods behind interfaces in the Core and reference those interfaces in the ViewModel project.
Core.dll
public class SomeModel {}
public interface ISomeModelRepositoryService
{
SomeModel GetById(int id);
void Save(SomeModel model);
}
Model.dll - this project implements Core's interfaces and contains only database methods (Entity framework in your case)
public class SomeModelRepositoryService : ISomeModelRepositoryService
{
public SomeModel GetById(int id)
{
//Entity framework code
}
public void Save(SomeModel model)
{
//Entity framework code
}
}
ViewModel.dll
public class SomeModelViewModel
{
private ISomeModelRepositoryService _RepositoryService;
public SomeModel Model { get; set; }
public SomeModelViewModel(ISomeModelRepositoryService repositoryService)
{
_RepositoryService = repositoryService;
}
public void Save()
{
_RepositoryService.Save(this.Model);
}
}
Create repository implementation instances in top startUp project(Main method for example) and put it to ViewModel as parameters:
ISomeModelRepositoryService repositoryService = new SomeModelRepositoryService();
SomeModelViewModel viewmodel = new SomeModelViewModel(repositoryService);
With this approach only "Model.dll" need to have references to Entity Framework
I'm trying to use Unit Of Work pattern for the first time in MVC application that already follows a Repository Pattern with Entity Framework DbContext.
My question is regarding the best place/practice on calling the Savechanges() method.
I see 2 approaches possible:
Call it in Unit Of Work class(Approach mentioned in Asp.Net site)
Call in Repository class
For the first approach, we have to call SaveChanges() on UnitOfWork instance injected in Controller.
For the second approach, SaveChanges() will be encapsulated in Repository and all Controller needs to do is invoke method in Repository(provided by UnitOfWork) and SaveChanges() will be called inside Repository.
Approach 1:
public class PostsController : Controller
{
private readonly IRepository<Post> _postRepository;
private readonly IRepository<Category> _categoryRepository;
private readonly IUnitOfWork _uow;
public PostsController(IUnitOfWork uow)
{
if (uow == null)
throw new ArgumentNullException(nameof(uow));
_uow = uow;
_postRepository = uow.Repository<Post>();
_categoryRepository = uow.Repository<Category>();
}
[HttpPost]
public ActionResult Create(Post post)
{
if (ModelState.IsValid)
{
_postRepository.Add(post);
_uow.SaveChanges();
}
return View(post);
}
}
public class UnitOfWork : IUnitOfWork
{
private CodingSoldierDbContext _dbContext;
private Dictionary<Type, object> _repositories = new Dictionary<Type, object>();
public UnitOfWork(DbContext dbContext)
{
if (dbContext == null)
throw new ArgumentNullException(nameof(dbContext));
_dbContext = dbContext as CodingSoldierDbContext;
}
public IRepository<T> Repository<T>() where T : class
{
if (_repositories.Keys.Contains(typeof(T)))
{
return _repositories[typeof(T)] as IRepository<T>;
}
IRepository<T> repository = new Repository<T>(_dbContext);
_repositories.Add(typeof(T), repository);
return repository;
}
public void SaveChanges()
{
_dbContext.SaveChanges();
}
}
public class Repository<T> : IRepository<T> where T : class
{
CodingSoldierDbContext _dbContext;
public Repository(DbContext dbContext)
{
if (dbContext == null)
throw new ArgumentNullException(nameof(dbContext));
_dbContext = dbContext as CodingSoldierDbContext;
}
public void Add(T item)
{
_dbContext.Set<T>().Add(item);
//_dbContext.SaveChanges();
}
}
Approach 2:
Not adding code so that question remains short.
In Approach 1, in Create method in Controller, remove the line:
_uow.SaveChanges();
Remove "SaveChanges" method definition from UnitOfWork.
Uncomment commented line in Repository Class:
_dbContext.SaveChanges()
I feel 2nd approach better than 1st approach in the sense code in controller is cleaner and SaveChanges is responsibility of the same class(Repository) who directly interact with DbContext.
Anyone, please let me know if you have any reason we should be following the 1st approach ?
I prefer to implement the SaveChanges on the UnitOfWork context because if you edit several entities from several repositories, you don't want to execute the save changes on each repository.
Example:
var unitOfWork = UnitOfWorkFactory.Create();
var categoryRepo = unitOfWork.GetRepository<Category>();
var postRepo= unitOfWork.GetRepository<Post>();
var cat = new Category("name");
categoryRepo.Add(cat);
var post = new Post("Title", "Message");
post.Category = cat;
postRepo.Add(post );
unitOfWork.SaveChanges();
It is easier to save the complete context (in one transition).
Both. In the UOW you need save changes to the context used by compound repositories. You need also savechanges method in the repositories like
public void SaveChanges()
{
context.SaveChanges();
}
For repository that is used independently
I am currently implementing EF6 to replace the ADO connection that currently exists.
I have read articles on why I should/shouldn't use the Repository pattern.
However I'm still not sure how to correctly call the repository pattern.
My project is layered as:
Presentation
Business Layer
Business Objects
Data Access Layer
Web Services
In the DAL I add my EF6 connection to my DB.
I created a IRepository and Repository classes.
Should the Business Layer be the one to call the Repository class?
If so I'm missing the connection here on how to call it.
Repository class:
public class MyRepository<T> : IRepository<T> where T : class
{
protected DbSet<T> DbSet;
protected DbContext _context;
public MyRepository(DbContext dataContext)
{
_context = dataContext;
DbSet = dataContext.Set<T>();
}
#region IRepository
public int Save()
{
return _context.SaveChanges();
}
public void Insert(T entity)
{
DbSet.Add(entity);
}
public void Delete(T entity)
{
DbSet.Remove(entity);
}
public IQueryable<T> SearchFor(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
return DbSet.Where(predicate);
}
public IQueryable<T> GetAll()
{
return DbSet;
}
public T GetById(int id)
{
return DbSet.Find(id);
}
#endregion
}
My goal is to have MyRepository handle the 6 or so tables that I added in EF.
Where I am missing is how to implement this class in my business access layer.
I get the error
'MyEFConn' is a 'type' but is used like a 'variable'
My attempt at implementing it is:
MyRepository<"table from EF"> users = new MyRepository<"table from EF">(MyEFConn);
Which MyEFConn is my DbContext class..
public partial class MyEFConn: DbContext
I get the error 'MyEFConn' is a 'type' but is used like a 'variable'
This is because the constructor for MyRepository expects to be passed an instance of a DbContext. In your case that would be an instance of MyEFConn.
Ex:
MyEfConn context = new MyEfConn();
MyRepository<MyUsers> users = new MyRepository<MyUsers>(context);
I am working on ASP.NET MVC 4 project from scratch. I decided to start with the data access layer using Entity Framework 5 and Code First workflow. The company where I used to work was using very good implementation (in my opinion) of the Repository pattern including Repositories, Services, Abstract Factory for the Repositories and the Services and Unity for DI. I tried to redo it but it's just too complicated for me and will cost me a lot of time to replicate what I've been using there, so I decided to do some research and go with something lighter.
So I decided to use GenericRepository and UnitOfWork - far from what was the initial plan, but that was the implementation that was showing in most of my searches. So I did a very basic implementation (Just to the point where I'm sure I know what's going on, maybe even below my abilities to comprehend) and actually I think for this exact project it may be just enough but what I want is to be able to call additional custom methods on the different entities.
I think this gets a lot from the idea of generic repository, but if I try to go with some other implementation it's getting exponentially harder, so I wonder if there's a way to add this to my implementation without hurting too much the idea behind the generic Repository.
What I have now is the GenericRepository class :
public class GenericRepository<TEntity> where TEntity : class
{
internal DBContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(DBContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> Get()
{
IQueryable<TEntity> query = dbSet;
return query.ToList();
}
//just the standard implementation
and my UnitOfWork class :
public class UnitOfWork : IDisposable
{
private DBContext context = new DBContext();
private CustomerRepository customerRepository;
public CustomerRepository CustomerRepository
{
get
{
if (this.customerRepository == null)
this.customerRepository = new CustomerRepository(context);
return customerRepository;
}
}
private GenericRepository<Order> orderRepository;
public GenericRepository<Order> orderRepository
{
get
{
So as you may see my Order entity is using the GenericRepository but I made a test class CustomerRepository to use for my Customer entity.
For now this class CustomerRepository looks like this :
public class CustomerRepository : GenericRepository<Customer>
{
public CustomerRepository(DBContext context) : base(context) { }
}
and the idea is to add the methods that are explicitly for the Customer entity here. I'm not sure if this is correct, especially the way I call the constructor. However, what is the natural way to add those specific methods for the different entities? I don't mind to even take a step back to implement it better but I don't want to rush it cause I tried and at the moment the whole concept is too complicated for me and I want to be sure that I understand the things that I use in my code.
I think you are on the right track. Here is the generic repository that I use:
public interface IRepository<TEntity>
where TEntity : class
{
IQueryable<TEntity> GetAll();
IQueryable<TEntity> GetBy(Expression<Func<TEntity, bool>> predicate);
TEntity GetById(long id);
void Add(TEntity entity);
void Update(TEntity entity);
void Delete(TEntity entity);
}
public class Repository<TEntity> : IRepository<TEntity>
where TEntity : class
{
protected readonly DbEntities Context;
protected readonly DbSet<TEntity> Set;
public Repository()
{
Context = new DbEntities();
Set = Context.Set<TEntity>();
}
public virtual IQueryable<TEntity> GetAll()
{
return Set;
}
public virtual IQueryable<TEntity> GetBy(Expression<Func<TEntity, bool>> predicate)
{
return Set.Where(predicate);
}
public virtual TEntity GetById(long id)
{
return Set.Find(id);
}
public virtual void Add(TEntity entity)
{
Set.Add(entity);
Context.SaveChanges();
}
public virtual void Update(TEntity entity)
{
Set.Attach(entity);
Context.Entry(entity).State = EntityState.Modified;
Context.SaveChanges();
}
public virtual void Delete(TEntity entity)
{
Set.Remove(entity);
Context.SaveChanges();
}
}
// And assuming User is a data object with an Id property:
public interface IUserSpecificRepository
{
List<User> GetById(long id)
}
public class UserSpecificRepository : IUserSpecificRepository, Repository<User>
{
public virtual List<User> GetById(long id)
{
return GetBy(x => x.Id = id).ToList();
}
}
Notice that GetAll() and GetBy() return a queryable. This is to allow control of when the query expression gets converted to SQL and hits the database. Usually a call to ToList() will cause this. You can then inherit from this and any custom methods can make use of these two starter methods.
Also, As a general rule of thumb, you should never do a GetAll().ToList() like you have now. If you have a zilion records you will run into problems. It is also a performance issue if you are filtering down to a few records. GetAll().ToList().Where(x => x.Id = 1) basically gets all zillion records from the db into memory, then filters it down to one. You should instead do this GetAll().Where(x => x.Id = 1).ToList().
Hope this helps you along!