src/Client/Resolve-XrmEntityReference.ps1
|
<# .SYNOPSIS Resolve a lookup from column values. .DESCRIPTION Find the one row of LogicalName whose columns match Attributes (AND) and return its EntityReference, e.g. to fill a lookup during a data import. No match raises an error (or returns $null with IfExists); several matches always raise an error. With Cache, the resolutions (misses included) are stored in the caller's hashtable and reused: pass the same hashtable to every call of an import. .PARAMETER XrmClient Xrm connector initialized to target instance. Use latest one by default. (Dataverse ServiceClient) .PARAMETER LogicalName Table / Entity logical name of the row to find. .PARAMETER Attributes Hashtable of column = value conditions, all required. A $null value matches an empty column; an EntityReference, OptionSetValue or Money value is compared on its id or value. .PARAMETER Cache Hashtable owned by the caller, used to store and reuse resolutions. (Default: no cache) .PARAMETER IfExists Return $null when no row matches, instead of raising an error. .OUTPUTS Microsoft.Xrm.Sdk.EntityReference. Reference of the matching row. .EXAMPLE $accountRef = Resolve-XrmEntityReference -XrmClient $xrmClient -LogicalName "account" -Attributes @{ accountnumber = "A-0042" }; .EXAMPLE $cache = @{}; foreach ($line in $csvLines) { $contact = New-XrmEntity -LogicalName "contact" -Attributes @{ lastname = $line.LastName; parentcustomerid = (Resolve-XrmEntityReference -XrmClient $xrmClient -LogicalName "account" -Attributes @{ accountnumber = $line.AccountNumber } -Cache $cache -IfExists); }; $xrmClient | Add-XrmRecord -Record $contact | Out-Null; } .LINK https://github.com/AymericM78/PowerDataOps/blob/main/documentation/commands/Resolve-XrmEntityReference.md #> function Resolve-XrmEntityReference { [CmdletBinding()] [OutputType([Microsoft.Xrm.Sdk.EntityReference])] param ( [Parameter(Mandatory = $false, ValueFromPipeline)] [Microsoft.PowerPlatform.Dataverse.Client.ServiceClient] $XrmClient = $Global:XrmClient, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String] $LogicalName, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [Hashtable] $Attributes, [Parameter(Mandatory = $false)] [ValidateNotNull()] [Hashtable] $Cache, [Parameter(Mandatory = $false)] [switch] $IfExists ) begin { $StopWatch = [System.Diagnostics.Stopwatch]::StartNew(); Trace-XrmFunction -Name $MyInvocation.MyCommand.Name -Stage Start -Parameters ($MyInvocation.MyCommand.Parameters); } process { $criteria = ($Attributes.Keys | Sort-Object | ForEach-Object { $criterionValue = $Attributes[$_]; if ($criterionValue -is [Microsoft.Xrm.Sdk.EntityReference]) { $criterionValue = $criterionValue.Id; } elseif ($criterionValue -is [Microsoft.Xrm.Sdk.OptionSetValue] -or $criterionValue -is [Microsoft.Xrm.Sdk.Money]) { $criterionValue = $criterionValue.Value; } # Dataverse compares strings without case: so does the cache key "$($_.ToLowerInvariant())=$("$criterionValue".ToLowerInvariant())"; }) -join "|"; $cacheKey = "$($LogicalName.ToLowerInvariant())|$criteria"; $reference = $null; if ($PSBoundParameters.ContainsKey('Cache') -and $Cache.ContainsKey($cacheKey)) { $reference = $Cache[$cacheKey]; } else { $row = $XrmClient | Get-XrmRecord -LogicalName $LogicalName -Attributes $Attributes -Unique -AsEntity; if ($row) { $reference = New-XrmEntityReference -LogicalName $LogicalName -Id $row.Id; } if ($PSBoundParameters.ContainsKey('Cache')) { $Cache[$cacheKey] = $reference; } } if ($null -eq $reference -and -not $IfExists) { throw "No '$LogicalName' row matches $($criteria.Replace('|', ', '))."; } $reference; } end { $StopWatch.Stop(); Trace-XrmFunction -Name $MyInvocation.MyCommand.Name -Stage Stop -StopWatch $StopWatch; } } Export-ModuleMember -Function Resolve-XrmEntityReference -Alias *; Register-ArgumentCompleter -CommandName Resolve-XrmEntityReference -ParameterName "LogicalName" -ScriptBlock { param($CommandName, $ParameterName, $WordToComplete, $CommandAst, $FakeBoundParameters) $validLogicalNames = Get-XrmEntitiesLogicalName; return $validLogicalNames | Where-Object { $_ -like "$wordToComplete*" }; } |