passing keys vs passing instances and the versioned business object problem
i once joined a team in developing a procurement/bidding system in ASP.NET. it involved "project for bidding" creation, contractor's profile management (with lots of document uploads), and bid evaluation as the core functionalities. contractors have the option to change any of its profile ranging from pcab license to bank certifications anytime. one of the business rules was during bid evaluation, the profile of the contractor when he joined the project will be the ones to be evaluated.
this entails keeping a history of the profile of the contractors and tagging what version of it applies to a particular project he joined. the design was to include an integer Version field to tables where it fits (all tables with both the ProjectId and ContractorId fields).
to my surprise, classes are passing around ContractorId and VersionId as parameters. passing around keys in the business layer is not OOP imo. my usual design is coming from the UI, say selecting from a gridview, my codebehind gets the key from the gridview's datakeyscollection and i immediately construct the business object. after i've constructed the business object, all logic or any processing that it will pass through will just be passing around this class instance.
being just another consultant hired to finish the project, you don't have the right and time to change all these existing and working codes (we don't have automated tests) so i basically lived with it. could they have designed the classes to pass and receive Contractor instance instead, there would be minimal change in our code.
thinking about the same problem, i think i should have designed another Id (incremental identity) in the Contractor table (physical key), aside from the repeating ContractorId with its combination of VersionId. Unique constraint will be on ContractorId and VersionId columns. referencing tables will now use this Id field instead of the previous ContractorId field.
problem is, how do i generate the next ContractorId then with this design? i can only think about using my nemesis = SELECT MAX(ContractorId) + 1. Do you have any other resolutions for this, maybe let the database automatically generate this next ContractorId so i can eliminate this Select Max thingy which is prone for error?