As far as patterns go, I'd say the one large complex object that's built from a single stored procedure is suspect. I'm not sure if your caching is a requirement or just the current state of its implementation.
The pattern that I'm used to is a type of repository pattern, using operations that fill specific contracts. And those operations house one or many datasources that call stored procedures in the database that will be used to build ONE of those sub-graphs you speak of. With that said, if you're going to lazy load data from a database, then I can only assume that many of the object members are not used much of the time which furthers my point - break that object up.
A couple things about it:
- It can be chatty if the entire object is being used regularly
- It is fully injectable via the Operations
- The datasources contain the reader for the specific object, thus only performing ONE task (SOLID)
- Can be modified to use Entity Framework, without too much fuss
- Can be designed to implement an interface, making it more reusable
- Will require you to break up that proc into smaller, chewable pieces, which will likely only benefit you in the long run.
- The complex object shown in this diagram really shouldn't exist if only parts of it are going to be used. Instead, consider segregating those objects. However, it really depends on how this object is being used.
UPDATE:
Using your cache as the repository, I would probably approach it like this:
So basically, you store the legacy object, but in your operations, you use them to build more relavent DTOs that are returned to the client.