I've come across a situation where I need to shard a database (Oracle, but that doesn't particularly matter).
The gist of the problem is I have written a large-scale system in a fairly standard TDD-style, with repositories and services hidden behind interfaces. Dependency injection is used to implement particular versions of the services and repositories at runtime, with this functionality allowing for crazy client requirements (for example we migrated from MSSQL to Oracle in under a week, which would not have been possible if the architecture was not properly decoupled!).
The problem now arises that I need to shard off a large portion of the data into a separate archival system, for performance reasons. The table structure has to remain the same due to time constraints, and I would like the purity of the architecture to remain the same, with no one section of the system having knowledge of the inner workings of another. The system will need to be switched from one shard to another dynamically via a user input (what input this is is yet to be finalised).
So, the two ways I can think of to approach this issue are:
1 - Pass in the required connection string on creation of a repository. This is not ideal as it means that the service layer, or worse, the UI, needs to know about the underlying sharding. This will make the design very inflexible in future, and require things like the sit-in-front caching layer (a write-through cache implementation on top of the IService) to be updates so their methods take a connection string as a parameter, which just seems wrong.
2 - Create a new IConnectionProvider subsection of the system that abstracts the connection information for the repository. This would be more ideal, as the repositories would remain self-contained, but I cannot think of a good way to switch this implementation without having to specify the relevant interface as a parameter to each method call, which goes back to the service layer specifying which connection to use.
Does anyone have any experience with this issue, or any opinions on a preferably low-labor yet still fairly pure implementation in this situation?