Currently, my code is similar to this (shortened just to make a point):
DAL
Repository Interface
public interface IRepository<TEntity, in TKey>
{
IList<TEntity> GetAll();
TEntity Get(TKey id);
TEntity Add(TEntity item);
TEntity Update(TEntity item);
bool Remove(TKey id);
}
Base EF repository
public class BaseEFRepository<TEntity, TKey> : IRepository<TEntity, TKey> where TEntity: class, IEntity<TKey> where TKey: struct
{
protected readonly DbContext _dbContext;
public BaseRepository()
{
_dbContext = new MyDB();
_dbContext.Configuration.ProxyCreationEnabled = false;
_dbContext.Configuration.LazyLoadingEnabled = false;
}
public virtual TEntity Get(TKey id)
{
return _dbContext.Set<TEntity>().Find(id);
}
public virtual IList<TEntity> GetAll()
{
return _dbContext.Set<TEntity>()
.ToList();
}
public virtual TEntity Add(TEntity item)
{
_dbContext.Set<TEntity>().Add(item);
_dbContext.SaveChanges();
return item;
}
.....
.....
}
A sample implementation of the base repository
public interface IContactsRepository : IRepository<Contact, long>
{
Contact GetByEmployeeId(string empId, ContactType type);
IList<Contact> GetByEmployeeId(string empId);
}
public class ContactsRepository : BaseEFRepository<Contact, long>, IContactsRepository
{
public Contact GetByEmployeeId(string empId, ContactType type)
{
var contact = _dbContext.Set<Contact>()
.FirstOrDefault(d => d.EmployeeId == empId && d.ContactType == type);
return contact;
}
public IList<Contact> GetByEmployeeId(string empId)
{
var contacts = _dbContext.Set<Contact>()
.Where(d => d.EmployeeId == empId)
.ToList();
return contacts;
}
}
BLL
public class Contacts
{
public Contact Get(long id)
{
IContactsRepository repo = ResolveRepository<IContactsRepository>();
var contact = repo.Get(id);
return contact;
}
public Contact GetByEmployeeId(string empId, ContactType type)
{
IContactsRepository repo = ResolveRepository<IContactsRepository>();
return repo.GetByEmployeeId(empId, type);
}
.......
.......
}
Now, everything is fine. I can simply do something like this:
var _contacts = new Contacts();
var contact = _contacts.GetByEmployeeId("C1112", ContactType.Emergency);
The confusion started when I read this blog post, the author says that using code like:
IContactsRepository repo = ResolveRepository<IContactsRepository>();
is a bad technique and it's anti-pattern and one should inject everything at the root of code. I can't see how would I do this with repository pattern. I am consuming this using a WCF. So, how on earth would I inject everything from the first call in WCF? I can't get it. What am I missing here?
One last thing, in this case the WCF is the last layer, and it should be only aware of the layer before it, which is the BLL layer. If I am going to implement anything as the author of that blog suggested, I will make the WCF layer aware of the DAL layer, isn't that bad practice? correct me if I am wrong.
You need to use Constructor Injection and then compose your objects in the Composition Root.
When you use Constructor Injection, you inject the dependencies through the constructors, so your classes would look like something like this:
public class BaseRepository
{
protected readonly DbContext _dbContext;
//...
public BaseRepository(DbContext context)
{
_dbContext = context;
}
//...
}
public class ContactsRepository : BaseEFRepository<Contact, long>, IContactsRepository
{
//...
public ContactsRepository(DbContext context)
:base(context)
{
}
//...
}
public class Contacts
{
private readonly IContactsRepository m_ContactsRepository;
public Contacts(IContactsRepository contacts_repository)
{
m_ContactsRepository = contacts_repository;
}
public Contact Get(long id)
{
var contact = m_ContactsRepository.Get(id);
return contact;
}
//...
}
Then in the Composition Root your would compose all your objects together. Optionally via a DI container.
Here is an example of such composition that uses Pure DI:
var context = new MyDB();
context.Configuration.ProxyCreationEnabled = false;
context.Configuration.LazyLoadingEnabled = false;
var contacts = new Contacts(new ContactsRepository(context));
In a WCF application that is hosted in IIS, the Composition Root is a custom ServiceHostFactory. This answer provides more details about how to do that.
#Matthew's post should answer your question. However, I would like to mention one thing I noticed in your code in relation to the question. You should not try to manually resolve the dependency but it should be injected by the container. I have modified your code to show this behaviour:
public class Contacts
{
private IContactsRepository repo;
public Contacts(IContactsRepository injectedContactsRepository)
{
repo = injectedContactsRepository;
}
public Contact Get(long id)
{
var contact = repo.Get(id);
return contact;
}
//and other methods definitions...
}
You need to identify a seam suitable for use as a composition root.
For WCF, you need to get creative - you must create a custom ServiceHostFactory to intercept the correct place to compose your object root.
See for example this article and this article from Mark Seemann (author of "Dependency Injection in .Net" - a book I think you would find very useful).
Many free DI containers, such as Autofac, provide off-the-shelf support for WCF, which is probably the best approach.
I really can't recommend Seemann's book highly enough - it goes into a lot of detail about this.
You might also find this article on using Autofac DI with ASP.Net and a repository interesting.
Related
I'm working on a net Core WebApi project and implementing a Unit Of Work pattern to access records from the database.
Consider below class:
Unit of Work:
public class UnitOfWork : IUnitOfWork
{
public IBooksRepository Books { get; }
public ICatalogueRepository Catalogues { get; }
...
}
Api Controller:
public class StudentController: ApiController
{
private IUnitOfWork _unitOfWork;
public StudentController(IUnitOfWork UnitOfWork)
{
_unitOfWork = UnitOfWork;
}
public IActionResult Get()
{
var books = _unitOfWork.Books.GetAll();
return Ok(books);
}
}
}
Currently I'm retriving the records from the database using above method,
I would like to access the repository object something like this.
var books = _unitOfWork.Set<IBooksRepository>.GetAll();
Similar to Set<T> method in EntityFramework DBContext claas and the purpose is to make the controller class generic and to perform the get operation in a generic way.
How can I implement like a Set<T> method which finds the repository object from the UnitOfWork class?
I agree with the points of Robert Harvey. However, if you want to do this, a way to do it would be to refactor your code a bit and then use reflection:
You could refactor the code a bit:
public class UnitOfWork : IUnitOfWork
{
public IRepository<Book> Books { get; }
public IRepository<Catalogue> Catalogues { get; }
public IRepository<T> Set<T>()
{
var allProperties = this.GetType().GetProperties();
var property = allProperties.SingleOrDefault(p => p.PropertyType == typeof(IRepository<T>) );
return (IRepository<T>) property.GetValue(this);
}
}
This is just a starter/idea, you can adapt it more to your context (optimizations, personal options, etc.).
PS: You wrote "similar to EF's Set<T>", but then did not use the "entity type" to get the repository in your code example. You can further simplify my example to checking for T and returning T instead of IRepository<T>:
public T Set<T>()
{
var allProperties = this.GetType().GetProperties();
var property = allProperties.SingleOrDefault(p => p.PropertyType == typeof(T) );
return (T)property.GetValue(this);
}
However, this seems silly. I think there should be an IRepository<T> if you're going the "generic repository" route.
I usually use AsNoTracking when I'm not intending to write anything. How should I handle this in my service layer where dbContext is hidden behind it? (I treat EF core as repository because it is repository)
public class SomeService
{
//...
public SomeEntity GetById(int id)
{
return _dbContext.Find(id);
}
public SomeEntity GetReadonlyById(int id)
{
return _dbContext.SomeEntitities.AsNoTracking().SingleOrDefault(e => e.Id == id);
}
public SomeEntity Update(SomeEntity someEntity)
{
_dbContext.Update(someEntity);
_dbContext.SaveChanges();
}
}
public class SomeController
{
private readonly SomeService _someService;
//....
[HttpGet("{id}")]
public IActionResult Get(int id)
{
var someEntity = _someService.GetReadonlyById(id);
if (someEntity == null)
{
return NotFound();
}
return someEntity;
}
[HttpPut("{id}")]
public IActionResult Modify(int id, SomeEntity modified)
{
var someEntity = _someService.GetById(id);
if (someEntity == null)
{
return NotFound();
}
someEntity.Someproperty = modified.Someproperty;
_someService.Update(someEntity);
return Ok(someEntity);
}
}
Is there any better way to do this?
I can also define my service as follows:
public class SomeService
{
//...
public SomeEntity GetById(int id)
{
return _dbContext.AsNoTracking.SingleOrDefault(e => e.Id == id);
}
public SomeEntity Update(int id, SomeEntity someEntity)
{
var entity = _dbContext.SomeEntities.Find(id);
if (entity == null)
{
return null;
}
entity.Someproperty = someEntity.Someproperty;
_dbContext.Update(entity);
_dbContext.SaveChanges();
return entity;
}
}
public class SomeController
{
private readonly SomeService _someService;
//....
[HttpGet("{id}")]
public IActionResult Get(int id)
{
var someEntity = _someService.GetById(id);
if (someEntity == null)
{
return NotFound();
}
return someEntity;
}
[HttpPut("{id}")]
public IActionResult Modify(int id, SomeEntity modified)
{
var someEntity = _someService.Update(id, modified);
if (someEntity == null)
{
return NotFound();
}
return Ok(someEntity);
}
}
What is the better way?
Basically, it is more common problem.
It is often happens that optimized reading methods are not convenient for updating scenarios and convenient reading methods for updating scenarios have unnecessary overhead for reading only scenarios. I see 3 options here:
Ignoring all problems with performance and just use universal GetById from your first approach for reads and updates. Obviously, it is applicable for simple applications and may not be applicable for high-load applications.
Using CQRS. It means you will have completely separate data model for reads and updates. Since reads usually don't require the complex domain logic it allows you to use any optimizations like AsNoTracking method or even use a plain sql in repositories. It is applicable for complex apps and requires more code.
Trying to find some compromise between these two options according to your particular needs.
As noted in comments your SomeService looks like repository. Ideally, domain service should contain only business logic and shouldn't mix it with infrastructure features like AsNoTracking. Whereas repositories can and should contain infrastructure features like AsNoTracking, Include and etc.
No tracking queries are useful when the results are used in a read-only scenario. They are quicker to execute because there is no need to setup change tracking information.
You can swap an individual query to be no-tracking:
using (var context = new BloggingContext())
{
var blogs = context.Blogs
.AsNoTracking()
.ToList();
}
You can also change the default tracking behavior at the context instance level:
using (var context = new BloggingContext())
{
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
var blogs = context.Blogs.ToList();
}
Ideally, you should manage the infrastructure stuff in the repository level.
Here is my solution. It works.
BASE CLASS OF ALL SERVICES
public class ServicesBase
{
protected AppDbContext dbcontext { get; }
public ServicesBase(AppDbContext dbcontext)
{
this.dbcontext = dbcontext;
}
public void AsNoTracking()
{
dbcontext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
}
public void SaveChanges()
{
dbcontext.SaveChanges();
}
}
USING IN CONTROLLER
_masterService.AsNoTracking();
var master = _masterService.GetById(1);
master.WagePerSquareMeter = 21;
_masterService.SaveChanges();
//or dbcontext.SaveChanges(), both of them will ot affect the database.
How to call a new method which is implemented in the concrete class of an interface
I am using structure map IOC container.
public interface ICompanyRepository
{
IEnumerable<Company> GetAll();
Company Get(int id);
Company Add(Company item);
bool Update(Company item);
bool Delete(int id);
}
public class CompanyRepository: ICompanyRepository
{
// Provide implementation for all interface methods
//Class CompanyRepository will also have the new method called DisplayLog
public void DisplayLog()
{
//To do
}
}
I am trying to implement DI using structure map in my Customer controller class
how can I tell the that I need methods ofcompany2 to be called?
_.Scan(x =>
{
x.TheCallingAssembly();
x.AddAllTypesOf<ICompanyRepository>();
// or
});
My code:
private readonly ICustomerRepository customerRepository;
public CustomerController(ICustomerRepository CustomerRepository)
{
customerRepository = CustomerRepository;
}
// GET: Customer
public ActionResult Index()
{
var customers = customerRepository.DisplayLog()
//Here i need to call CompanyRepository class methods DisplayLog() how can i call it here ?
// method DisplayLog() is not be shown here
return View(customers);
}
On an Interface, you can only call what is defined in the Interface - Its a definition of a "common base" of all classes that implement it. Ask yourself: What should happen if the ICompanyRepository you get is of a type that does NOT implement DisplayLog?
That means: It is not possible to call anything else than the interface methods right away.
To call DisplayLog on customerRepository there are 3 ways:
Add DisplayLog() to the Interface
Cast the customerRepository to CompanyRepository. but this will cause an exception, if the customerRepository is of any other type than CompanyRepository
Use a second interface
After all, I'm not quite sure if what you're doing is DI. In my understanding of DI it should be something like this:
public ActionResult Index(ILogDisplay display)
{
var customers = display.DisplayLog(customerRepository);
return View(customers);
}
ILogDisplay is being a new Interface for a separate class to be injected
public interface ILogDisplay
{
public YourResultType DisplayLog(ICustomerRepository);
}
In this example you actually inject a dependency (the implementation of ILogDisplay) in your class.
There's a couple of questions to raise here:
Why does the repository know how to display a log?
What does DisplayLog() mean in the context of a CustomerRepository?
Why should the controller even care about what the repository is logging?
Why is DisplayLog assigning a variable called customers when its return type is clearly void?
Fundamentally, the behaviour of your repository should be unknown to your controller, this is the essence of the Inversion of Control principle. All it cares about is that given the explicit contract provided by the interface for a repository, a method call will return customers. Logging is a concern of the repository.
A fairly traditional setup, from a DI point of view us the following:
ICompanyRepository:
public interface ICompanyRepository() {
IEnumerable<Company> GetAll();
Company Get(int id);
Company Add(Company item);
bool Update(Company item);
bool Delete(int id);
}
CustomerRepository:
public class CompanyRepository: ICompanyRepository
{
private readonly ILogger logger;
public CompanyRepository(ILogger logger) {
this.logger = logger;
}
// Provide implementation for all interface methods
public Company Get(int id) {
var customers = this.randomCustomerSource.Get(id);
this.logger.Info("Whatever you want to log here");
return customers;
}
}
CustomerController:
public class CustomerController {
private readonly ICustomerRepository customerRepository;
public CustomerController(ICustomerRepository CustomerRepository)
{
customerRepository = CustomerRepository;
}
// GET: Customers
public ActionResult Index()
{
var customers = customerRepository.GetAll()
return View(customers);
}
}
So the repository requests an Ilogger, the controller requests a ICompanyRepository, and will just call GetAll() and return the results. Usually there's a bit more involved but that's the very basic gist of a workflow for a controller that returns data.
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 am new in Moq and Unit Testing. I want to test my Repository and Unit of Work pattern with entity framework 5. But I don't understand where and how can I start.
My Repository Interface :
public interface ISmRepository<T>
{
void Add(T entity);
void Remove(T entity);
void Update(T entity);
IQueryable<T> SearchFor(Expression<Func<T, bool>> expression);
IQueryable<T> GetAll();
T GetById(Int64 id);
}
My Repository:
public class SmReporitory<T> : ISmRepository<T> where T : class, IEntity, new()
{
private readonly DbSet<T> _dbSet;
private readonly DbContext _dbContext;
public SmReporitory(DbContext dbContext)
{
_dbSet = dbContext.Set<T>();
_dbContext = dbContext;
}
public void Add(T entity)
{
_dbSet.Add(entity);
}
public void Remove(T entity)
{
_dbSet.Remove(entity);
}
public void Update(T entity)
{
_dbContext.Entry(entity).State = EntityState.Modified;
}
public IQueryable<T> SearchFor(Expression<Func<T, bool>> expression)
{
return _dbSet.Where(expression);
}
public IQueryable<T> GetAll()
{
return _dbSet;
}
public T GetById(long id)
{
return _dbSet.FirstOrDefault(x => x.Id == id);
}
}
My Unit Of Work Interface :
public interface ISmUnitOfWork : IDisposable
{
ISmRepository<BreakdownCause> BreakdownCasus { get; }
ISmRepository<BreakDownType> BreakDownTypes { get; }
ISmRepository<CompanyInformation> CompanyInformations { get; }
void Save();
}
My Unit Of Work Implementation :
public class SmUnitOfWork : ISmUnitOfWork
{
private readonly DbContext _dbContext;
private ISmRepository<BreakDownType> _breakDownTypes;
private ISmRepository<BreakdownCause> _breakdownCasus;
private ISmRepository<CompanyInformation> _companyInformations;
public SmUnitOfWork() : this(new SmDbContext())
{
}
public SmUnitOfWork(SmDbContext smDbContext)
{
_dbContext = smDbContext;
}
public ISmRepository<BreakdownCause> BreakdownCasus
{
get { return _breakdownCasus ?? (_breakdownCasus = new SmReporitory<BreakdownCause>(_dbContext)); }
}
public ISmRepository<BreakDownType> BreakDownTypes
{
get { return _breakDownTypes ?? (_breakDownTypes = new SmReporitory<BreakDownType>(_dbContext)); }
}
public ISmRepository<CompanyInformation> CompanyInformations
{
get { return _companyInformations ?? (_companyInformations = new SmReporitory<CompanyInformation>(_dbContext)); }
}
public void Save()
{
try
{
_dbContext.SaveChanges();
}
catch
{
throw;
}
}
public void Dispose()
{
if (_dbContext!=null)
{
_dbContext.Dispose();
}
}
Now I want to test ISmRepository interfaces method's.
I already referenced NUnit and Moq in a class library project. Now I need a starting point.
You really don't need to test your repositories as you have them written. The reason is that, as Mystere Man alluded, you're basically just wrapping the Entity Framework API. When working with EF and using either my own repositories or some DbContext I don't worry about testing these data access calls until integration testing time for the reasons already stated.
However, you can (and should) certainly mock your repositories and unit of work to test all of your other code that has dependencies on them. By testing your repositories you're really testing Entity Framework functionality and I'm sure that has been tested more thoroughly than you will. One thing you can do is not put business logic into your repositories that directly interact with EF but instead move that out to another layer that utilizes your repositories for data access.
The short answer is that you really can't. At least not fully. And the reason for that is that a moq'd EF context does not behave the same way as a real one does due to the inherent sql translation.
There is a lot of code that will pass a Moq'd context, but will blow up in a real one. As such, you cannot depend on Moqing of fakes with an EF context, and you have to use integration testing.