So I'm following a tutorial about dependency injection with Unity in C#. In the tutorial, they used repository classes as an example to demonstrate the concept. Trying to apply that to one of sample projects, I encountered an inheritance problem. So I have
public interface IRepository<T> where T : class
{
List<T> GetAll();
T Get(int id);
void Add(T entity);
void SaveChanges();
}
public class Repository<T> : IRepository<T> where T : class
{
private CoffeeMachineDbContext context = null;
protected virtual DbSet<T> DbSet { get; set; }
public Repository()
{
context = new CoffeeMachineDbContext();
DbSet = context.Set<T>();
}
public Repository(CoffeeMachineDbContext context)
{
this.context = context;
}
public virtual List<T> GetAll()
{
return DbSet.ToList();
}
public virtual T Get(int id)
{
return DbSet.Find(id);
}
public virtual void Add(T entity)
{
DbSet.Add(entity);
}
public void SaveChanges()
{
context.SaveChanges();
}
}
The repository class implements the interface and the common methods.
Now To be able to apply dependency injection as it was explained (or at least as I understood it), I created a new interface named IClientRepository that inherits from IRepository as follow:
public interface IClientRepository : IRepository<Client>
{
Order GetLastOrder(int id);
}
Notice that the interface declares a new method that it's specific to clients context.
Finally, the implementation of the IClientRepository interface is:
public class ClientRepository : Repository<Client>, IClientRepository
{
/// <summary>
/// Gets the client's last order
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public Order GetLastOrder(int id)
{
Order lastOrder = null;
Client client = DbSet.Find(id);
if (client != null)
{
lastOrder = client.Orders.OrderByDescending(o => o.DateCreated).FirstOrDefault();
}
return lastOrder;
}
I don't need to implement the IRepository methods because they are common between all others.
The issue that I'm facing is that when I'm trying to register type in the unity container as follow:
container.RegisterType<IClientRepository, ClientRepository>(new HierarchicalLifetimeManager());
I get the following error
The type 'CoffeeMachine.Models.Repositories.ClientRepository' cannot be used as type parameter 'TTo' in the generic type or method 'UnityContainerExtensions.RegisterType(IUnityContainer, LifetimeManager, params InjectionMember[])'. There is no implicit reference conversion from 'CoffeeMachine.Models.Repositories.ClientRepository' to 'CoffeeMachine.Models.Repositories.IClientRepository'.
Does anyone have any idea what I did wrong here?
That error happens because your class doesn't actually implement IClientRepository.
You can only cast an instance to an interface if its class actually implements that interface.
Related
I am making a generic repository but for some entities I also need functionalities not provided by the generic repository. I have an interface IGenericRepository and concrete implementation as GenericRepository with basic CRUD operations. Further I have a studentRepository that uses the generic repository but also has functionalities of its own independent from the Generic Repository for which i have an Interface called IStudentRepository.
Here is the sample code:
public interface IGenericEntityRepository<T>
{
Delete(T entity);
T Get(int id);
IEnumerable<T> GetAll();
Add(T entity);
Update(T entity);
}
public class GenericEntityRepository<T> : IGenericEntityRepository<T> where T : class
{
protected readonly ApplicationDbContext _applicationDbContext;
public GenericEntityRepository(ApplicationDbContext applicationDbContext)
{
this._applicationDbContext = applicationDbContext;
}
//Generic Repository Implementations....
}
public interface IStudentRepository
{
string GetFullName(Student student)
double GetGpa(Student student)
}
public class StudentRepository: GenericRepository<Student>, IStudentRepository
{
public StudentRepository(ApplicationDbContext applicationDbContext) : base(applicationDbContext)
{}
//IStudentRepository functions' implementations...
}
Now I need to inject this StudentRepository to my StudentsController
public class StudentsController : Controller
{
private readonly IGenericEntityRepository<Student> _genericStudentRepository;
public StudentsController(IGenericEntityRepository<Student> _genericStudentRepository)
{
this._genericStudentRepository = genericRepository;
}
public void testAccessibility()
{
this._genericStudentRepository.GetAll() //valid call
this._genericStudentRepository.GetAllGpa() //invalid Call
***As expected cause IGenericEntityRepository doesn't have that ***function
}
}
As you can see the probelem here, if I inject IGenericEntityRepository I only get the genericrepository functionalities. If i want the functionalities of Student repository not included in genericRepository I have to inject both IGenericEntityRepository and IStudentRepository like below and vice versa.
public class StudentsController : Controller
{
private readonly IGenericEntityRepository<Student> _genericStudentRepository;
private readonly IStudentRepository _studentsRepository;
public StudentsController(IGenericEntityRepository<Student> _genericStudentRepository, IStudentRepository studentsRepository)
{
this._genericStudentRepository = genericRepository;
this.__studentsRepository = studentsRepository;
}
public void testAccessibility()
{
this._genericStudentRepository.GetAll() //valid call
this._studentsRepository.GetAllGpa() //valid call
}
}
Is there a better way to do this? Doesn't feel right injecting two contextually same but coding wise different objects like this.
You can have IStudentRepository extend IGenericEntityRepository<T>:
public interface IStudentRepository : IGenericEntityRepository<Student>
{
string GetFullName(Student student)
double GetGpa(Student student)
}
Now injecting IStudentRepository should be enough to use all the functions.
i have this existing code
public interface IRepository<T>
{
void Create(T obj);
T Retrieve(string key);
}
public class ItemRepository : IRepository<Item>
{
public void Create(Item obj)
{
//codes
}
public Item Retrieve(string key)
{
//codes
}
}
i would like to create a General class repository where i have to inject a type of IRepository to the constructor then use its own implementation of the methods. i already have an existing code but it is currently wrong
public class Repository
{
IRepository<T> action = null;
public Repository(IRepository<T> concreteImplementation)
{
this.action = concreteImplementation;
}
public void Create(T obj)
{
action.Create(obj);
}
}
the classes are from EF. if there is no work around for this what will be the best approach?
If I understand you correctly you want a single repository which can create or retrieve an object of any type by delegating to a type specific repository implementation?
How do you imagine this working? you defined this Repository class, but you have to create a concrete implementation of the actual repository in order to use it, and then still have to create an instance of Repository anyway. Why not just use the generic implementation you have to create anyway?
And what about your Retrieve method? How will this look in your Repository class? Will you just return Object? or will you make your method generic?
Anyway to answer your question, you could do this I suppose:
public class Repository
{
IRepository action = null;
public Repository(IRepository concreteImplementation)
{
this.action = concreteImplementation;
}
public void Create<T>(T obj)
{
action.Create(obj);
}
}
but you have to introduce a non generic interface as well, as you can't require an interface with a generic parameter in the constructor without specifying the generic type on the class.
public interface IRepository
{
void Create(object obj);
object Retrieve(string key);
}
Or possibly you could pass in the type into the Create method instead of having a generic parameter:
public class Repository
{
IRepository action = null;
public Repository(IRepository concreteImplementation, Type respositoryType)
{
this.action = concreteImplementation;
expectedType=repositoryType;
}
public void Create(Type type, Object obj)
{
if(type==expected && obj.GetType()==type)
{
action.Create(obj);
}
}
}
but both of these are terrible ideas. Just use the generics and create a repository per type, it'll be best in the long run
I think you might just be missing the definition of T in the context of the general repository class.
Try adding <T> to the it like this:
public class Repository<T>
{
...
}
I've found that in my UnitOfWork I have a repository for each type of entity and am not using aggregate roots, so I'm trying to fix that. Tackling the idea of computer inventory, I currently have my UnitOfWork structured as such:
public class UnitOfWork : IUnitOfWork
{
private readonly ReportingDbContext _dbContext = null;
public UnitOfWork()
{
_dbContext = new ReportingDbContext();
}
public void Commit()
{
_dbContext.SaveChanges();
}
// Inventory
public IRepository<ComputerEntity> Computers {get { return new Repository<ComputerEntity>(_dbContext); }}
public IRepository<NetworkAdapterEntity> NetworkAdapters { get { return new Repository<NetworkAdapterEntity>(_dbContext); } }
// plus a bunch more
}
I want only my aggregate root to appear there, which should be easy enough to do. I think the issue is that I'm using a single repository class and feeding in the type when I new it up. I believe the answer is to have multiple repositories, each one corresponding to an aggregate root. What is nice about this one generic repository that I'm using for each type is that it handles all my Entity Framework stuff like finding by ID, saving to the DbSet, etc. My generic repository is setup as such:
public class Repository<T> : IRepository<T> where T : class
{
protected DbContext DbContext { get; set; }
protected DbSet<T> DbSet { get; set; }
public Repository(DbContext dbContext)
{
if (dbContext == null)
{
throw new ArgumentNullException("dbContext");
}
DbContext = dbContext;
DbSet = DbContext.Set<T>();
}
public IQueryable<T> GetAll()
{
return DbSet;
}
public IQueryable<T> Find(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
return DbSet.Where(predicate);
}
// the rest of the implementation omitted for brevity
}
This repository uses an interface that all my yet-to-be-created aggregate root repositories should use:
public interface IRepository<T> where T : class
{
IQueryable<T> GetAll();
IQueryable<T> Find(Expression<Func<T, bool>> predicate);
T GetById(int id);
void Remove(T entity);
void Add(T newEntity);
}
Now here is the real meat of the question. I have the above interface implemented nicely in my concrete Repository class, and I want that same functionality in all the aggregate root repositories that I will be making. I don't want to ever directly use this generic repository, as I just want to use it for a base to get at the basic CRUD stuff it does with Entity Framework. I don't want to repeat the already implemented generic repository stuff, just inherit it. More importantly, I want to design this correctly the first time.
Would it be appropriate to create my aggregate root based repository as such:
public interface IComputerRepository
{
string ComputerSpecificMethod(string param);
}
public class ComputerRepository : Repository<ComputerEntity>, IComputerRepository
{
public ComputerRepository(DbContext dbContext) : base(dbContext)
{
//
}
public string ComputerSpecificMethod(string param)
{
// do stuff
return "test";
}
}
Then use this new fancy repository (and others like it) in my UnitOfWork as such:
public IRepository<ComputerEntity> Computers {get { return new ComputerRepository(_dbContext); }}
Instead of:
public IRepository<ComputerEntity> Computers {get { return new Repository<ComputerEntity>(_dbContext); }}
The goal is to stick to the UnitOfWork/Repository pattern, and I'm unsure if this is the proper way of doing this.
I found that the way to do this that works for me is to have the interface for each custom repository in my unit of work class as such:
public IInventoryRepository Computers { get { return new InventoryRepository(_dbContext); } }
It is implemented in its own class of course. To get it to inherit properly, I did this:
public class InventoryRepository : GenericRepository<ComputerEntity>, IInventoryRepository
{
public InventoryRepository(DbContext dbContext) : base(dbContext)
{
}
// your custom methods go here
}
I then can use this in my WCF service as such:
using (var uoW = new UnitOfWork())
{
var repo = uoW.Computers;
var computerEntity = repo.FindComputerByHostname(hostname, client);
// do more stuff
}
Here is my design of domain model and generic repository
public interface IEntity
{
long Id { get; }
}
public interface IRepository<T> where T : class, IEntity, new()
{
void Save(T entity);
void Delete(long id);
T Get(long id);
IEnumerable<T> GetAll();
}
public interface IUserRepository : IRepository<User>
{
User Login(string username, string password);
}
public class User : IEntity
{
// Implementation of User
}
public abstract class BaseRepository<T> : IRepository<T> where T : class, IEntity, new()
{
// Implementation of IRepository
}
public class UserRepository : BaseRepository<User>, IUserRepository
{
// Implementation of IUserRepository
// Override BaseRepository if required
}
When I want to instantiate a repository instance I use a factory which implements following interface
public interface IRepositoryFactory
{
R CreateRepository<R, T>()
where R : IRepository<T>
where T : class, IEntity, new();
}
And use the factory object as below
1. IRepositoryFactory factory = CreateFactory();
2. IUserRepository repository = factory.CreateRepository<IUserRepository, User>();
3. User user = repository.Login("user", "1234");
My problem is in the second line. I would like to use my factory like.
// Without specifying the User type parameter
factory.CreateRepository<IUserRepository>()
Since my IRepository interface has contstraint on type of entity my factory uses same constraint to satisfy IRepository requirement.
Is there any way to isolate this parameter from client?
I agree with the others that you would benefit from looking at a DI/IoC framework like Ninject.
So this answer is not a suggestion to not follow the other advices. But still, there are ways for you to solve your problem at a lower level. This code is not tested very well, but you could do something like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using NUnit.Framework;
namespace TestConsole1
{
public interface IEntity
{
long Id { get; }
}
public interface IRepository<T> where T : class, IEntity, new()
{
void Save(T entity);
void Delete(long id);
T Get(long id);
IEnumerable<T> GetAll();
}
public interface IUserRepository : IRepository<User>
{
User Login(string username, string password);
}
public class User : IEntity
{
// Implementation of User
public long Id
{
get { return 42; }
}
}
public abstract class BaseRepository<T> : IRepository<T> where T : class, IEntity, new()
{
// Implementation of IRepository
public void Save(T entity)
{
throw new NotImplementedException();
}
public void Delete(long id)
{
throw new NotImplementedException();
}
public T Get(long id)
{
throw new NotImplementedException();
}
public IEnumerable<T> GetAll()
{
throw new NotImplementedException();
}
}
public class UserRepository : BaseRepository<User>, IUserRepository
{
// Implementation of IUserRepository
// Override BaseRepository if required
public User Login(string username, string password)
{
return new User();
}
}
class Factory
{
public T CreateRepository<T>() where T : class
{
//TODO: Implement some caching to avoid overhead of repeated reflection
var abstractType = typeof(T);
var types = AppDomain.CurrentDomain.GetAssemblies().ToList()
.SelectMany(s => s.GetTypes())
.Where(p => p.IsClass &&
!p.IsAbstract &&
abstractType.IsAssignableFrom(p));
var concreteType = types.FirstOrDefault();
if (concreteType == null)
throw new InvalidOperationException(String.Format("No implementation of {0} was found", abstractType));
return Activator.CreateInstance(concreteType) as T;
}
}
class Program
{
static void Main(string[] args)
{
var factory = new Factory();
var userRepo = factory.CreateRepository<IUserRepository>();
Console.WriteLine(userRepo.GetType());
User user = userRepo.Login("name", "pwd");
Console.WriteLine(user.Id);
Console.ReadKey();
}
}
}
As this code reveals, a central point is that you will need to handle the coupling between your interface and the concrete class, for example between your IUserRepository and your UserRepository. If you do not handle this relation in a direct way via a mapper or similar you can implement a more automatic way like the one that is illustrated in the code.
However, if you use something like Ninject instead to handle this for you, it will be a better investment of your time as you will most likely find that the complexity of your factory class will grow significantly over time.
Br. Morten
There are 3 problems with your code:
First is IEntity. Having single type of ID is against DDD, because in DDD, identity of object is given by domain and it can be anything from string, int, guid to complex type.
Second is generic repository with IRepository, which again, is highly useless, because you will rarely pass this interface and mostly will pass interface for repository for concrete entity.
Third thing is that in DDD repositories should exist only for aggregate roots, which is not reflected in your design.
If you fix this, you will find out, that implementation of interface of repository for specific entity can easily be suplied by DI framework.
I am new to LINQ to SQL and attempting to create a generic Data Access Object (DAO) for the basic Create, Read, Update, and Destroy (CRUD) methods so that I can reuse the code. I was successful in creating a generic method that will delete any entity by using the code below but, I was wondering if anyone knows how to create a generic method that will select any entity by a common Id field that exists on all tables.
/// <summary>
/// Generic method that deletes an entity of any type using LINQ
/// </summary>
/// <param name="entity"></param>
/// <returns>bool indicating whether or not operation was successful</returns>
public bool deleteEntity(Object entity)
{
try
{
DomainClassesDataContext db = new DomainClassesDataContext();
db.GetTable(entity.GetType()).Attach(entity);
db.GetTable(entity.GetType()).DeleteOnSubmit(entity);
db.SubmitChanges();
return true;
}
catch(Exception ex)
{
Console.WriteLine(ex.StackTrace);
return false;
}
}
I am pretty sure that the same patter will work for update and insert and would like to have a generic method on the GenericDAO that will retrieve me any entity (i.e. Customer, Invoice, WorkOrder, etc...) based on the entities Id. Thanks in advance for the replies.
I think you are looking for Repository Pattern, the following is a simple implementation of it:
First you need to create an interface IRepository like this:
public interface IRepository<T> where T : class
{
void Add(T entity);
void Delete(T entity);
void Update(T entity);
IEnumerable<T> All();
...
}
Then:
public class Repository<T> : IRepository<T>
where T : class, IEntity
{
DataContext _db;
public Repository()
{
_db = new DataContext("Database string connection");
_db.DeferredLoadingEnabled = false;
}
public void Add(T entity)
{
if (!Exists(entity))
GetTable.InsertOnSubmit(entity);
else
Update(entity);
SaveAll();
}
public void Delete(T entity)
{
GetTable.DeleteOnSubmit(entity);
SaveAll();
}
public void Update(T entity)
{
GetTable.Attach(entity, true);
SaveAll();
}
System.Data.Linq.Table<T> GetTable
{
get { return _db.GetTable<T>(); }
}
public IEnumerable<T> All()
{
return GetTable;
}
}
Then :
public class CustomerRepository : Repository<Customer>
{
public ProductRepository()
: base()
{
}
}
Then you can have something like:
Customer newCustomer = new Customer { FistName = "Foo", LastName = "Boo" };
_customerRepository.Add(newCustomer);
Where Customer is an entity mapped to your database which is defined in the .dbml. This is just a start, see the following for more details:
Implementing Repository Pattern in LINQ-to-SQL.
LINQ to SQL and Repository Pattern.
Implementing IRepository Pattern in LINQ to SQL.
Implementation example of Repository Pattern in LINQ to SQL.