Polymorphic Lookups in Dataverse

Loading

1. Introduction to Polymorphic Lookups

Polymorphic lookups (also called “party list” fields) in Dataverse allow a single lookup field to reference multiple entity types. This powerful feature enables flexible relationship modeling where a field can point to different tables depending on context.

Key Characteristics

Single field stores references to multiple entities
Resolves to the correct record type at runtime
Used in core Dataverse features like Activities and Notes
Supports custom entities beyond system tables

Common Use Cases

  • Assigning tasks to users, teams, or roles
  • Document ownership by accounts or contacts
  • Generic commenting systems
  • Multi-entity relationship tracking

2. Native vs. Custom Polymorphic Lookups

A. Native Polymorphic Fields

These come preconfigured in standard Dataverse tables:

FieldSupported Entities
OwnerUser, Team
RegardingAccount, Contact, Opportunity, Custom Entities
CustomerAccount, Contact

B. Custom Polymorphic Lookups

You can create your own by:

  1. Setting Target Record Types in the lookup definition
  2. Using the EntityReference data type programmatically

3. Implementing Custom Polymorphic Lookups

Step 1: Create the Field

# PowerShell using Pac CLI
Add-CrmCustomField `
  -EntityLogicalName "new_customentity" `
  -FieldName "new_polymorphiclookup" `
  -DisplayName "Related Record" `
  -FieldType Lookup `
  -Targets "account","contact","systemuser"

Step 2: Configure via UI

  1. Navigate to Maker Portal → Tables → Your Table → Columns
  2. Create a Lookup column
  3. Under Target record types, select multiple entities

Step 3: Programmatic Access

// C# SDK Example
var entityRef = new EntityReference(
  logicalName: "account", // or "contact", etc.
  id: Guid.Parse("00000000-0000-0000-0000-000000000001"));

entity["new_polymorphiclookup"] = entityRef;

4. Querying Polymorphic Data

FetchXML Example

<fetch>
  <entity name="task">
    <attribute name="subject"/>
    <attribute name="regardingobjectid"/>
    <filter>
      <condition 
        attribute="regardingobjectid" 
        operator="eq" 
        value="00000000-0000-0000-0000-000000000001" />
    </filter>
  </entity>
</fetch>

Web API Query

GET /api/data/v9.2/tasks?$select=subject,_regardingobjectid_value&
  $filter=_regardingobjectid_value eq 00000000-0000-0000-0000-000000000001

Resolving References

// Client-side resolution
var regardingObj = Xrm.Page.getAttribute("regardingobjectid").getValue();
if (regardingObj) {
  var entityType = regardingObj.entityType; // "accounts", "contacts", etc.
  var id = regardingObj.id;
}

5. Advanced Implementation Patterns

Pattern 1: Dynamic UI Based on Reference Type

// Show/hide fields based on polymorphic selection
function onPolymorphicFieldChange() {
  var lookup = Xrm.Page.getAttribute("new_polymorphiclookup").getValue();

  if (lookup) {
    switch(lookup.entityType) {
      case "account":
        Xrm.Page.ui.tabs.get("tab_account").setVisible(true);
        break;
      case "contact":
        Xrm.Page.ui.tabs.get("tab_contact").setVisible(true);
        break;
    }
  }
}

Pattern 2: Plugin Handling for Multiple Types

public void Execute(IServiceProvider serviceProvider)
{
    var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
    var target = (Entity)context.InputParameters["Target"];

    if (target.Contains("new_polymorphiclookup"))
    {
        var entityRef = (EntityReference)target["new_polymorphiclookup"];

        switch(entityRef.LogicalName)
        {
            case "account":
                // Account-specific logic
                break;
            case "contact":
                // Contact-specific logic
                break;
        }
    }
}

Pattern 3: Virtual Entity Resolution

// Resolve to different external systems
var entityRef = new EntityReference(
  logicalName: GetEntityTypeFromExternalId(externalId),
  id: GetLocalIdFromExternalId(externalId));

6. Performance Considerations

Optimization Strategies

ScenarioRecommendation
Large datasetsAdd filtered views on lookup fields
Complex joinsPre-cache reference types
Bulk operationsDisable plugins during import

Indexing Guidance

Standard polymorphic fields are automatically indexed
Custom fields may need manual index creation
Composite indexes improve join performance


7. Limitations and Workarounds

Key Limitations

  1. No custom UI for type selection (uses standard lookup control)
  2. Cannot enforce different relationships per type
  3. Advanced filtering requires careful query design

Workarounds

// Custom lookup dialog with type filtering
function openCustomLookup() {
  var options = {
    entityTypes: ["account", "contact"],
    defaultViewId: "00000000-0000-0000-0000-000000000001"
  };
  Xrm.Navigation.openLookup(options);
}

8. Security Implications

Access Control

Field-level security applies uniformly
Record sharing follows referenced entity permissions
Auditing tracks all reference changes

Best Practices

  1. Validate reference types in plugins
  2. Implement row-level security filters
  3. Monitor for broken references

9. Real-World Examples

Example 1: Service Ticket System

graph LR
    A[Service Ticket] --> B[Related To]
    B --> C[Account]
    B --> D[Contact]
    B --> E[Equipment]

Example 2: Document Management

graph TD
    F[Document] --> G[Owned By]
    G --> H[User]
    G --> I[Team]
    G --> J[Department]

Example 3: Project Tracking

graph BT
    K[Project Task] --> L[Responsible Party]
    L --> M[Employee]
    L --> N[Vendor]
    L --> O[Contractor]

10. Troubleshooting Guide

IssueDiagnosisSolution
Lookup shows wrong typeIncorrect resolutionClear browser cache
Query returns no resultsMissing join conditionUse link-entity in FetchXML
Plugin fails on referenceNull check missingValidate EntityReference exists
Performance degradationMissing indexCreate custom index

11. Future Enhancements

Expected Improvements

  1. Enhanced lookup dialogs with type filtering
  2. Strongly-typed SDK support
  3. Graph API integration

Community Solutions

PCF controls for better UI
Open-source type resolvers


Leave a Reply

Your email address will not be published. Required fields are marked *