It all depends on how and where you load your data....
If you create and fill all your objects in public constructors, then yes, you'll create this chain or tree of objects. You create one object that in turn creates one or more objects that in turn create even more objects. But, if this is what you need, then why not? Why not have the User object create a collection of Roles that each have a separate RoleDescription (in the form of a NameValue object for example). You may end up with 20 or 30 different objects, but that shouldn't be a problem.
If you expect a large tree, both in terms of depth and in terms of the number of records, then you need to be careful. Let's assume you model a Programmer class that has a Projects collection that holds all the projects a developer has worked on. Each project would have a Client property (or a Clients collection) that in turn have a ContactPersons collection. This means that by loading a single Programmer, you could end up with 30 projects, an additional 37 Clients and maybe another 100 address records, totalling up to 168 objects. Again, if you need it, you may be able to get away with it, but obviously there is some sort of turning point where memory consumption and performance (loading objects, firing queries and so on) is no longer acceptable.
One solution is to create a Load method that loads the data:
Programmer myProgrammer = new Programmer();
// At this point, nothing has been loaded yet.
// But now we load data:
As an alternative to an instance Load method, you could do the same with a static GetItem method.
To make the loading process a bit more fine-grained, you can create an overload that accepts a (custom) LoadTypes enum. For example:
Then in Load you would only load the data for the requested part.
A final alternative is "lazy loading" which basically postpones getting the data until it's necessary. A simple example of a property could look like this:
private List<Client> clients;
public List<Client> Clients
if (clients == null)
clients = GetClientsFromDatabase()
client = value;
Wether this works OK in a web app depends on the design. Sometimes, getting all data up front in one fell swoop (chunky calls) may give you better results that getting everything in little pieces (chatty calls). So, your mileage may vary.
Maybe it's time we make the discussion a little more concrete? Maybe you can describe the system you're designing in a bit more detail? It's easier to think about real world objects than about hypothetical object1 and object3 objects.... ;)
Everyone is unique, except for me.
Author of ASP.NET 2.0 Instant Results
and Beginning Dreamweaver MX / MX 2004
Want to be my colleague? Then check out this post