1

I am trying to figure out how to correctly implement UoW and Repository pattern with Entity Framework. I saw a lot of post against it but it still seems like the right way to go.

I am trying to do it according to this blog post. The last thing I am trying to figure out is how to inject the Repositories into the UoW but in a way that lets me do it on demand. The number of repositories may grow and so will the constructor then. Furthermore instantiating all of the repositories for an operation that may require only 1 or 2 seems like a waste of resources.

How do I do it in a way that lets me write unit tests fairly easily?

The only way I found out, that lets me inject repositories NOT in the constructor (so they are not all instantiated, even when they are not needed for a particular operation) is by doing it in the getter:

private IGenericRepository<Blog> _blogRepository;
private IGenericRepository<Post> _postRepository;
public UnitOfWork(BloggingContext bloggingContext)
{
    _bloggingContext = bloggingContext;
}

public IGenericRepository<Blog> BlogRepository
{
    get
    {
        return _blogRepository = _blogRepository ?? new GenericRepository<Blog>(_bloggingContext);
    }
}

However, this approach generates a lot of noise in the code because when I will have 50 repositories I will need 50 props.

imagran
  • 45
  • 1
  • 3
  • 1
    It seems to me that what you want to achieve is not UoW but a set of UoWs realized in one class, depending on a given operation. I would first question why you want to do this. After that yes you could just use lazy construction by creating the repo in demand. If you want to avoid many props, use a generic method of type T and keep the repos in a dictionary or cncurrent dictionary indexed by T – Sentinel Apr 22 '18 at 11:42
  • @Sentinel I wanted to do a standard UoW+Repository pattern not a set of UoW. All the repos in one UoW should share the DbContext. The second part, about the method of T is a great suggestion. I found this https://stackoverflow.com/questions/16064902/dependency-injection-in-unit-of-work-pattern-using-repositories?rq=1 and it is similar to what you suggested with the dict. – imagran Apr 22 '18 at 12:52
  • 1
    they also mention Lazy which might help you. – Sentinel Apr 22 '18 at 13:24
  • @Sentinel Well, my last concern is that with the dict approach I would have to do some ugly casting on every use :/ Any suggestions? edit. I could use a factory in UoW to get all the repositories on demand. That should work nicely? – imagran Apr 22 '18 at 14:24
  • @catdoanyrhing33 Not sure why you would need to cast everywhere, just return T in a generic get method. So you would have var X=get(); off the top of my head that doesn't need a cast right? – Sentinel Apr 22 '18 at 17:46
  • passing factories around also works. A lazy instantiator accepting a generic parameter can be thought of as a type of factory. – Sentinel Apr 22 '18 at 17:48
  • I have limited experience with IoC containers. For some reason most projects I have been on avoided them. IMO IoC sometimes makes code less readable. I think if you have good enough reason to pass in some kind of factory, or factory configuration, go ahead. Sometimes worrying about antipatterns can just be counterproductive – Sentinel Apr 23 '18 at 05:22
  • The point of the factory is that you can specify what type of repo to use, eg EF, in-memory, or other backend dataaccezs implementations. Generally this is overkill. DBs tend never to change, meaning you ain't going to be switching from EF to Azure NoSQL and you don't want to program for that scenario – Sentinel Apr 23 '18 at 05:31
  • Well done with the implementation. – Sentinel Apr 23 '18 at 05:32

1 Answers1

0

You might want to combine the described approach (which I like) with the generic repository approach described here https://cpratt.co/truly-generic-repository/ Given proper implementation of the UoW pattern from the blog post you reference, you won't need the anything but the IReadOnlyRepository from the article - it will provide everything you need for the repository to be.

achekh
  • 1,106
  • 7
  • 20