Sometimes in a multi-tier system, designers tend to follow rigid object-oriented design rules to perform heavy data-centric manipulations in the middle tier. Remember, a thin line separates the operations that the middle tiers should handle and those that the database should handle. One should judge with care where the operation logically belongs, while keeping in mind the performance benefits of alternative approaches. I have seen design teams waste a lot of resources and energy deciding whether to have such operations in the middle tier or in databases (data storage and services).
For example, it makes more sense to me to perform complex joins between different tables at the database level and get the desired recordset back to the middle tier. An object model may toy with the idea of having many “Gets” (such as making various simple selects on each table) using separate data access component operations, with each one bringing data from a particular table. While more object oriented, this approach results in unwanted data in the middle tier and extra processing to retrieve the desired record set from this chunk. These can be avoided altogether with the previous approach.
To stress again, using stored procedures as much as possible further enhances performance. Using stored procedures also helps in the basic aim of any design: to separate the business logic from the data storage.