21

I have a ASP.NET web site which uses domain driven design and uses repository for its database operations.
I want to know that what is pros and cons of singleton repository and static repository and simple repository class which will new on every access?
further more if anyone can compare and guide me to use which one of them I will be appreciate.

onof
  • 17,167
  • 7
  • 49
  • 85
JGC
  • 12,737
  • 9
  • 35
  • 57

4 Answers4

20

Static and singleton aren't good solution for Repository pattern. What if your application will use 2 or more repositories in the future?

IMO the best solution is to use a Dependency Injection container and inject your IRepository interface in the classes that need it.

I suggest you to read a good book about domain driven design and a good book about dependency injection (like Mark Seeman's Dependency Injection in .NET).


With singletons and static classes your application won't be scalable

You have two singleton repositories:

class Repository<TEntity> {

  static Repository<TEntity> Instance { get { ... /*using sql server*/ } }
}

class Repository2<TEntity> {

  static Repository2<TEntity> Instance { get { ... /*using WCF or XML or any else */ } }
}

The services using them must have a static reference to one of them or both:

class OrderService {

    public void Save(Order order) { Repository<Order>.Instance.Insert(order); }
}

How can you save your order using Repository2, if the repository is statically referenced?

A better solution is using DI:

interface IRepository<TEntity> { ... }

class SqlRepository<TEntity> : IRepository<TEntity> { ....}

class OrderService {
    private readonly IRepository<TEntity> _repo;

    public OrderService(IRepository<TEntity> repo) { _repo = repo; }

    public void Save(Order order) { repo.Insert(order); }
}
onof
  • 17,167
  • 7
  • 49
  • 85
8

Don't use static or singleton repositories because of:

  • It affects testablility, you can not mock it when unit testing.

  • It affects extensibility, you can not make more than one concrete implementation and you can not replace behavior without re-compiling.

  • It affects scalability in terms of lifecycle management, insetead depend on dependency injection framework to inject the dependency and manage lifecycle.

  • It affects maintainability, it forces dependency upon concrete implementation instead of abstraction.

Bottom line: DONT use static or singleton repositories

instead create repository interfaces in your domain model project, and implement these interfaces in a concrete data access project, and use dependency injection framework.

Mohamed Abed
  • 5,025
  • 22
  • 31
6

Two SOLID reasons to not have singleton repository:

  • Consumers of repository will be coupled to repository implementation. This will negatively affect extensibility and testabiliy. This is a DIP violation. Depend on abstractions, not on concretions.

  • Repository implementation will have to violate SRP because it will most likely end up managing ORM session, database connection and potentially transactions. It would also have to make thread safe guarantees because it potentially can be used from multiple threads. Instead, database connection (ORM Session) should be injected into repository implementation so that consuming code can arrange multiple repository calls into transaction.

Possible solution to both problems is Constructor Injection.

Dmitry
  • 17,078
  • 2
  • 44
  • 70
6

I personally respectfully disagree with previous answers.

I have developed multiple websites (one with 7 millions page views per month) and never had a single problem with my static repositories.

My static repository implementation is pretty simple and only contains objects providers as properties. A single repository can contain as many providers as you need.

Then, the providers are responsible to manage database connection and transactions. Using TransactionScope, the consumer could manage the transactions or let it to the providers.

Every providers are developed using the singleton pattern.

This way, I can get my objects by simply calling this :

var myObj = MyRepository.MyProvider.GetMyObject(id);

At any time, there is only one repository and one provider of each type in every web pool of my application. Depending on how many users you have at the same time on your site, you could set more than one web pool (but most of the time one is just enough).

I don't see where my repository/providers consumers are coupled with my repository. In fact, the implementations of my providers are totally abstracted from them. Of course, all providers returned by my repository are interfaces and I could easily change the implementation of them at any time and push my new dll on the web server. If I want to create a completely new provider with the same interface, I only have to change it in ONE place: my repository.

This way, no need to add dependency injection or having to create your own ControllerFactory (for MVC procjects).

And you still have the advantage of clean code in your controllers. You will also save a lot of repository creation and destruction every time a page is requested (which normally use reflection in your ControllerFactory).

If you are looking for a scalable solution (if you really need it which most of the time is not really a problem), my way of developing repositories should never be a problem compared to dependency injection.

Alwin
  • 69
  • 1
  • 1