I'm building an ORM based on the repository pattern. Inside the repository I create something that I call a "data source" to fetch results from the db and map them to entity objects. Each data source is created with a query, and is responsible for getting either a single result for the first row, or all results. While the data source is mainly responsible to fetch get either a single or all objects from a (prepared) query, it also works as a proxy to a "cursor" that is setup during creation of the data source. I put the cursor into quotes, because it actually is an array of primary keys, which are later used to fetch entities from the repository using these IDs. This cursor-like implementation is due to SQLite which just doesn't offer anything better in that case in regards to cursors.
So the data source provides singleEntity(), allEntities(), firstEntity(), nextEntity(), previousEntity(), entityAtIndex(). As said before, all but the first two are actually utilizing the cursor. The cursor is created from the same query as the data source (but auto-optimized to limit selected fields for the cursor).
The repository itself provides the CRUD functionality (getById(), remove(), create(), update()).
That could be all good and well, most of that is just common pattern implementation... But just now I realize the following problem:
Even though it is the the repository itself that should be used to fetch entities by ID, a data source within the repository may just use a different projection for the data - or only a subset of the available. Thus it may return different or just some alternate mapping to what the default repository getEntityById() would return.
How should the design be changed? 1) Disallow other mappings than the default repo getter? => Would be bad design, probably. How to control queries for data sources etc. 2) Force the user to setup custom queries for the cursor for creating the index + fetcher query for fetching individual results by id? => Better than previous idea, but would also mean probable place for inconsistency in case the cursor fetcher is setup different from the data source result mapping. 3) Hopefully something that I didn't think about yet. I still can easily redesign the complete API