A colleague of mine was working with a customer authoring rules using irX for Dynamics® and irAuthor. I've taken the liberty of almost entirely fictionalizing the details, this isn't a verbatim account of our discussion.
He wondered, "Are the virtual lookup entities in CRM dynamics based on the Rule App Entity context you are in? I always thought lookups in CRM point at a specific instance of an Entity but when I add a Customer field and look at the schema source it says 'Virtual Lookup'! Oh yeah, and what's with this 'CustomerLookup' entity that gets added to my rule app? It seems shifty."
He also noted that this 'CustomerLookup' character pointed at a CRM field called customerid. But that its' Account and Contact fields were backed by a "Microsoft Dynamics® CRM: Virtual Lookup Entity". He called shenanigans, exclaiming how its' shifty nature was confirmed by the internal schema source of the CustomerLookup entity and that he would shortly clear the CustomerLookup and its' Virtual Lookup Entity scourge from the rule app. Better judgement prevailed though, and he decided to ask me about it first before taking action.
In a lot of ways, he's absolutely right. CustomerLookup is indeed a shifty creature, but it's really only shifty because it's an abstraction covering up a rather cumbersome (and therefore error-prone) way of writing rules using some CRM attribute (field) data types.
Take the Case built-in CRM Entity. It has a Customer field that refers to either an Account or a Contact. This makes sense if you think about it. Support could open a Case to track an interaction with a Contact. After investigating, Support determines that a follow-up would be needed with the Product Manager and Sales, so they open a separate Case, but this time they set the Customer field of the Case to the Customer's Account entity. If we were to state the data hierarchy it might be something like this:
- An Account has one or more Contacts
- An Account may have a Parent Account; Accounts may have one or more child Accounts
- An Account may have one or more Cases
- A Case has a Contact
- If the Customer is an Account, the Contact must be present in the Account's Contacts collection
- If the Customer is a Contact, the Contact field must be blank (null)
- A Case has a Customer
- The Customer will refer to EITHER an Account OR a Contact record
- The Customer MAY refer to the Case's Contact but is not obligated to do so
Everything above we can map pretty much 1:1 with our rule app shcema, up until we get to "If the Customer is a…". There, it seems as if we are stuck because InRule doesn't natively support inheritance and polymorphic behavior in entity schemas*. So how then do we express this type of field that can be one type OR another? Enter the Virtual Lookup Entity.
The Virtual Lookup Entity has a single purpose in life, and that purpose is to provide a way at design-time to disambiguate and more importantly, write validatable rules against these types of objects. In order to be able to do this, it takes the approach of using an attribute (field) flag to signal what type of Entity the attribute refers to (Account or Contact). Going back to our original question, we can answer this now by saying that the CustomerLookup entity is a wrapper for the Virtual Lookup Entity, which in turn is a pointer to a record that may or may not exist within Dynamics at rule execution time.
The last statement there is the key to understanding the overall role of these Virtual Lookup Entities. The concept is used in other places of the InRule Dynamics Integration framework, such as when creating a new entity record and associating it to an existing one. Under the hood, the framework puts in a placeholder Virtual Lookup Entity so that when the set of commands to issue to CRM are compiled and collated, records are created and updated in the proper order.
Now that the Customer data type is available for custom entities (as of Dynamics 2016 Update 1/SP1), more and more folks want to make use of it in their data models and in their rules. For rules authors, there's no special need to add and set any ID's of records and such - just write rules the way you're used to writing them and let the framework handle all the heavy lifting. When you want to determine what type of record a Customer is, you should check the CustomerType property; it will tell you directly 'Account' or 'Contact'. Similarly, if you are creating a new Customer entity, make sure to set its' CustomerType field to the appropriate value of either Account or Contact. Checking one or the other for null isn't a good approach because it's possible that both are null, and it's likely you still want to treat the field as one type or the other.
* This isn't strictly true, because you can certainly bind and reference a .NET assembly containing a rich object hierarchy, but because of the limitations and risks of that approach it's true enough for this discussion