1

My project structure is like this. I have an interface IUnitOfWork which has inside it

 void Commit();
 MyContext Context { get; }
 void Register(BaseRepository<IEntity> repository);

This is my UnitOfWork class

public class UnitOfWork : IUnitOfWork
{
    private readonly Dictionary<string, BaseRepository<IEntity>> repositories;

    public MyContext Context { get; }

    public UnitOfWork()
    {
        repositories = new Dictionary<string, BaseRepository<IEntity>>();
        this.Context = new MyContext();
    }

    public void Commit()
    {
        repositories.ToList().ForEach(x => x.Value.Submit());
    }

    void IUnitOfWork.Register(BaseRepository<IEntity> repository)
    {
        repositories.Add(repository.GetType().Name, repository);
    }
}

My IBaseRepository interface

public interface IBaseRepository<T> where T : class, IEntity
{
    List<T> GetAll(Func<T, bool> filter = null);

    void Save(T item);

    void Create(T item);

    void Update(T item, Func<T, bool> findByIDPredecate);
}

My IEntity interface

public interface IEntity
{
    int Id { get; set; }
}

 public abstract class BaseRepository<TEntity> : IBaseRepository<TEntity>
        where TEntity : class, IEntity
{
    public BaseRepository(IUnitOfWork unitOfWork)
    {
        unitOfWork.Register(this);

But I am getting this compiler error

Error CS1503 Argument 1: cannot convert from 'Repositories.BaseRepository<TEntity>' to 'Repositories.BaseRepository<DataAccess.Interfaces.IEntity>'

However I am explicitly specifying that the TEntity will be of type IEntity (or it will inherit of it). Why is this happening?

Camilo Terevinto
  • 31,141
  • 6
  • 88
  • 120
john
  • 11
  • 1
  • Regardless of the problem, why is a Repository registering itself in a Unit of Work? – Camilo Terevinto May 20 '18 at 17:35
  • @CamiloTerevinto I read this https://stackoverflow.com/questions/16064902/dependency-injection-in-unit-of-work-pattern-using-repositories?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa here.. Anyway with a few words, I will be using Dependecy injection and this way the repository will register itself when needed – john May 20 '18 at 17:39
  • @CamiloTerevinto any idea why I am getting the compiler error? – john May 20 '18 at 17:43
  • Yeah, it's called variance. The linked question shows a non-generic `IRepository` interface that you did not copy. – Camilo Terevinto May 20 '18 at 17:48
  • I know why you are getting the error, but it is hard to explain. The reason is because `T` is invariant so it cannot be both `IEntity` and `TEntity`. I am sure if you removed the `GetAll` method, it will work (I do not have Visual Studio but that is my guess). Basically what you are trying makes no sense logically. – CodingYoshi May 20 '18 at 17:49
  • @CamiloTerevinto now I thought, what if I want to concrete repository to have other methods different than the base repository? – john May 20 '18 at 17:50
  • That's when the entire pattern goes down, and one of the reasons I see absolutely no value in the UoW/Repository mess. You'd have to convert to the actual type every time – Camilo Terevinto May 20 '18 at 17:52
  • If you are using Entity Framework, it already does UOW. Just make sure you use the same context in all your repositories. – CodingYoshi May 20 '18 at 17:54
  • So basically I should remove my UnitOfWork class and just inject the context with a Dependency injection container right? – john May 20 '18 at 17:56
  • I think [this](https://stackoverflow.com/a/50380618/4228458) will help with the error you are getting. As for UOW, imagine you have 2 repositories and add an item to each (customer, order). As long as both repos share the same DbContext, when you call `SaveChanges`, it will do the whole thing in one transaction. Either both customer and order will get saved or none of them. I am not sure what you are planning to do in your repo.Save method but you better not be committing changes to the db. I personally think you should rename that method Add. – CodingYoshi May 20 '18 at 18:03

0 Answers0