There are four different kind of relationships in the force.com platform.
But I like to categorize them in a slightly different way than the help pages:
- Lookup
- Master-Detail
- Hierarchy
- Standard relationships
There are lot's of help topics and articles on Lookup and Master-Detail, such as the relationship overview and the relationship considerations topics in help. I don't like including Many-to-Many in this kind of discussion because, for all intents and purposes M:M is just an implementation of two M-D relationships (by strict reading of the docs), or possibly two lookup relationships or a mix of the two.
To dispense quickly with hierarchy relationships, these are a special lookup self-join relationship on the User object. Read up on those on your own. :-)
So let me talk about my own invented fourth category.
Standard Relationships
If we (salesforce.com) provide you with a relationship between two objects, that is a standard relationship. Not lookup, not master-detail. Why do I bother providing this fourth category? Because it is the easiest way to stop people trying to categorize them as either lookup or master-detail when they often share characteristics of both. When you approach working with any standard relationship the question you really need to answer is, "how does this standard relationship behave." Frequently standard relationships have characteristics that you just can't do with a custom relationship. Ever tried to make a custom relationship polymorphic? Go ahead...give it a try. You will fail. But there are many examples of polymorphic standard relationships.
I like to categorize these in their own separate place independent of lookup/master-detail. In fact, anything standard follows the same rule: it behaves exactly the way that salesforce.com wants it to behave to fit the particular purpose of that standard thing.
In my opinion, the Account-Contact relationship is a perfect justification for this fourth category: it is a little like lookup, a little like Master-Detail, but fundamentally behaves the way it does because we decided it should.
That might not be the "proper" way, as you ask, but it is the one that makes the most sense to me.
I can't offer you any insight into why you cannot do this, you just can't unfortunately, it's a seemingly arbitrary limitation of the platform and the Product2
object. Unless someone who knows about the internals of the platform comes across this I doubt you'll ever get a definitive answer.
In terms of working around it though, the only way to achieve this is to create your lookup as a standard non-required Lookup and then enforce that the value of this lookup cannot be blank using a validation rule.
Your validation rule will look something like this:
ISBLANK(ProductId__c)
If the Product is deleted then this will result in the value of the field being cleared, as per the default 'Clear the value of this field.' behaviour, which will prevent you updating the child record until a valid lookup ID is entered.
If you want to change this behaviour you'll have to write a before delete
trigger on Product2 with your desired logic.
Best Answer
If its a lookup you will need a simple trigger to do this in real time
This is if you are planning to do a real time delete .Also in this case be sure to check with business what if someone undeletes a record from the bin.May be a trigger to handle this as well
Also if you don't need a real time delete ,a batch process to fetch orphaned childs(ParentId is null) and delete .