Web API PowerShell Polymorphic Lookup sample
This PowerShell sample demonstrates how to work with polymorphic lookup columns (also known as multi-table lookups) using the Dataverse Web API:
- Creating multiple tables that can be referenced by a single lookup column
- Creating a polymorphic lookup attribute using the
CreatePolymorphicLookupAttributeaction - Creating records and associating them through the polymorphic lookup
- Retrieving records with polymorphic lookup values and identifying referenced entity types
- Exporting and importing a managed solution containing the tables and relationships
This sample uses the common helper libraries created as described in Use PowerShell and Visual Studio Code with the Dataverse Web API. These functions are defined in the MetadataOperations.ps1 file. You can find descriptions and examples in Dataverse Web API PowerShell Helper Metadata operations
Prerequisites
Before running this sample you should read these articles that explain concepts and patterns used by these samples:
- Quick Start Web API with PowerShell and Visual Studio Code
- Use PowerShell and Visual Studio Code with the Dataverse Web API
- Multi-table (polymorphic) lookups
This sample requires:
Visual Studio Code. See Download Visual Studio Code
PowerShell extension for Visual Studio Code. See PowerShell for Visual Studio Code
PowerShell 7.4 or higher. See Install PowerShell on Windows, Linux, and macOS
Az PowerShell module version 11.1.0 or higher. See How to install Azure PowerShell
To update an existing installation to the latest version, use
Update-Module -Name Az -ForceAccess to Dataverse with privileges to perform data operations.
How to run the sample
Clone or download the PowerApps-Samples repository.
Open the PolymorphicLookupSample.ps1 file using Visual Studio Code
Edit this line to use the URL of the environment you want to connect to:
Connect 'https://yourorg.crm.dynamics.com/'(Optional) Set the
$deleteCreatedRecordsvariable to$falseif you do not want to delete the records this sample creates.Press F5 to run the sample.
The first time you run the sample a browser window opens. In the browser window, enter or select the credentials you want to use to authenticate.
To connect as a different user, run the Disconnect-AzAccount command.
Demonstrates
This sample has 9 sections:
- Create Publisher and Solution
- Create Referenced Tables
- Create Referencing Table
- Create Polymorphic Lookup Attribute
- Create Sample Data Records
- Retrieve Sample Data
- Export Managed Solution
- Delete Sample Tables and Solution
- Import and Delete Managed Solution
Section 0: Create Publisher and Solution
Operations: Create a solution record and an associated publisher record.
- After first checking whether these records already exist using the Get-Records function, the script creates them if they don't exist using the New-Record function. These functions are in the TableOperations.ps1 file.
- All solution components created in this sample get associated to the solution, so they can be exported. This association is created using the
MSCRM.SolutionUniqueNamerequest header setting the solution unique name set as the value. - All names of solution components are prefixed using the publisher customization prefix.
Section 1: Create Referenced Tables
Operations: Create three tables that a polymorphic lookup on sample_Media can reference.
- For each table (
sample_Book,sample_Audio,sample_Video), the script first checks whether the table already exists using the Get-Tables function. - If it doesn't exist, each table is created using the New-Table function.
- Table labels are constructed using the New-Label function.
- The primary name attribute for each table is constructed using the New-PrimaryNameAttribute function.
- Each table includes a secondary string attribute specific to the media type:
sample_CallNumberfor books,sample_AudioFormatfor audio, andsample_VideoFormatfor video.
Section 2: Create Referencing Table
Operations: Create the sample_Media table that will hold the polymorphic lookup column.
- The script first checks whether the table already exists using the Get-Tables function.
- If it doesn't exist, the table is created using the New-Table function.
- Table labels are constructed using the New-Label function and the primary name attribute using the New-PrimaryNameAttribute function.
Section 3: Create Polymorphic Lookup Attribute
Operations: Create a single sample_MediaPolymorphicLookup lookup attribute on sample_Media that can reference records in sample_Book, sample_Audio, or sample_Video.
- The script first checks whether the lookup already exists by querying the
sample_media_sample_bookrelationship using the Get-Relationships function. - If the lookup doesn't yet exist, it is created using the New-PolymorphicLookupColumn function, which calls the
CreatePolymorphicLookupAttributeaction. This creates one lookup attribute and three one-to-many relationships in a single request. The second and third relationships include a customCascadeConfiguration. - After creating the lookup, the
ReferencingEntityNavigationPropertyNamefor each of the three relationships is retrieved using the Get-Relationships function. These navigation property names are required when setting the lookup value via@odata.bind.
Section 4: Create Sample Data Records
Operations: Create records in each of the four tables and link sample_Media records to referenced records through the polymorphic lookup.
- Retrieves the entity set name for each table using the Get-Table function.
- Creates two
sample_Bookrecords, twosample_Audiorecords, and twosample_Videorecords using the New-Record function. - Creates four
sample_Mediarecords, each linking to a different referenced record via the polymorphic lookup using the@odata.bindsyntax with the navigation property name retrieved in Section 3.
Section 5: Retrieve Sample Data
Operations: Query the sample_Media table to display each record's polymorphic lookup value and the type of the referenced entity.
- Retrieves all
sample_Mediarecords including the lookup value column using the Get-Records function. - Uses OData annotations (
@OData.Community.Display.V1.FormattedValueand@Microsoft.Dynamics.CRM.lookuplogicalname) to display the referenced record's display name and entity type. - Demonstrates a cross-table query by separately retrieving
sample_Mediarecords that reference a specificsample_Bookrecord and a specificsample_Audiorecord using the Get-Records function.
Section 6: Export Managed Solution
Operations: Export the solution containing the items created in this sample using the Export-Solution function.
Section 7: Delete Sample Tables and Solution
Operations:
- Deletes the
sample_Mediatable first, which cascades to also delete the polymorphic lookup attribute and its three relationships, as well as allsample_Mediadata records, using the Remove-Record function. - Deletes each referenced table (
sample_Book,sample_Audio,sample_Video) using the Remove-Record function. Deleting each table also removes all its data records. - Retrieves and deletes the unmanaged solution using the Get-Records function and the Remove-Record function.
Section 8: Import and Delete Managed Solution
Operations:
- Imports the solution exported in Section 6 using the Import-Solution function.
- Queries the solution table to get the ID of the imported solution using the Get-Records function.
- Deletes the imported solution using the Remove-Record function.
Clean up
By default, this sample deletes all the records it creates.
If you want to view created records, after the sample is completed, change the deleteCreatedRecords variable to false and you're prompted to delete the records if desired.
Note
If you don't delete the unmanaged solution components created by this sample, the code in Section 8 fails.
Console Output
The complete output to the console should look something like this:
PS C:\GitHub\PowerApps-Samples\dataverse\webapi\PS>
PS C:\GitHub\PowerApps-Samples\dataverse\webapi\PS> . 'C:\GitHub\PowerApps-Samples\dataverse\webapi\PS\PolymorphicLookup\PolymorphicLookupSample.ps1'
Example Publisher created successfully
Polymorphic Lookup Example Solution created successfully
Book table created successfully
Audio table created successfully
Video table created successfully
Media table created successfully
Polymorphic lookup attribute 'sample_MediaPolymorphicLookup' created successfully
Attribute ID: 611d231d-938a-46ec-ab95-ee8a2bf178fc
Relationship IDs: ec8e9781-5117-f111-8342-0022482aa3a2, f48e9781-5117-f111-8342-0022482aa3a2, fc8e9781-5117-f111-8342-0022482aa3a2
Navigation property names:
Book: sample_MediaPolymorphicLookup_sample_book
Audio: sample_MediaPolymorphicLookup_sample_audio
Video: sample_MediaPolymorphicLookup_sample_video
Entity set names:
Book: sample_books
Audio: sample_audios
Video: sample_videos
Media: sample_medias
Created Book record: Content1 (1ww-3452) - ID: 8b98de92-5117-f111-8341-7ced8d1dd398
Created Book record: Content2 (a4e-87hw) - ID: 145dfa93-5117-f111-8341-7ced8d21aac6
Created Audio record: Content1 (mp4) - ID: 8f4c5a95-5117-f111-8342-0022482aa3a2
Created Audio record: Content2 (wma) - ID: c5712b97-5117-f111-8341-0022482aa957
Created Video record: Content3 (wmv) - ID: 4b227d95-5117-f111-8341-0022482aa60e
Created Video record: Content2 (avi) - ID: 974c5a95-5117-f111-8342-0022482aa3a2
Created Media record: Media Object One -> Book:First Book - ID: e47bd998-5117-f111-8341-7ced8d1dd398
Created Media record: Media Object Two -> Audio:First Audio - ID: d1712b97-5117-f111-8341-0022482aa957
Created Media record: Media Object Three -> Video:First Video - ID: d3712b97-5117-f111-8341-0022482aa957
Created Media record: Media Object Four -> Audio:Second Audio - ID: 59227d95-5117-f111-8341-0022482aa60e
-- Retrieving Media records with polymorphic lookup values --
Media catalog entries:
Media Object Four -> [sample_audio] Content2 (ID: c5712b97-5117-f111-8341-0022482aa957)
Media Object Two -> [sample_audio] Content1 (ID: 8f4c5a95-5117-f111-8342-0022482aa3a2)
Media Object Three -> [sample_video] Content3 (ID: 4b227d95-5117-f111-8341-0022482aa60e)
Media Object One -> [sample_book] Content1 (ID: 8b98de92-5117-f111-8341-7ced8d1dd398)
Demonstrating cross-table lookup: querying Media records
where the referenced item is named 'Content1'
Media records referencing Book 'Content1':
- Media Object One
Media records referencing Audio 'Content1':
- Media Object Two
Managed solution exported to C:\GitHub\PowerApps-Samples\dataverse\webapi\PS\PolymorphicLookup\polymorphiclookupexamplesolution.zip
Deleting sample tables and solution...
sample_Media table deleted.
sample_Book table deleted.
sample_Audio table deleted.
sample_Video table deleted.
Unmanaged solution 'polymorphiclookupexamplesolution' deleted.
Managed solution imported.
Managed solution deleted.
Sample completed in 00:19:36