Public/CRUD.txt

function New-CrmRecord {
    # .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml
    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
 
        [parameter(Mandatory=$true, Position=1, ParameterSetName="NameAndFields")]
        [string]$EntityLogicalName,
 
        [parameter(Mandatory=$true, Position=2, ParameterSetName="NameAndFields")]
        [hashtable]$Fields,
 
        [parameter(Mandatory=$true, Position=1, ParameterSetName="CrmRecord")]
        [PSObject]$CrmRecord,
 
        [parameter(Mandatory=$false, Position=2, ParameterSetName="CrmRecord")]
        [switch]$PreserveCrmRecordId
    )
 
    $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))
 
    if($null -eq $conn) {
        throw "Dataverse connection is null."
    }
 
    try {
        if($null -ne $CrmRecord) {
 
            $EntityLogicalName = $CrmRecord.ReturnProperty_EntityName
 
            if([string]::IsNullOrEmpty($EntityLogicalName)) {
                throw "CrmRecord does not contain ReturnProperty_EntityName."
            }
 
            $entity = New-Object Microsoft.Xrm.Sdk.Entity($EntityLogicalName)
 
            if($PreserveCrmRecordId -and $CrmRecord.ReturnProperty_Id) {
                $entity.Id = [Guid]$CrmRecord.ReturnProperty_Id
            }
 
            $atts = Get-CrmEntityAttributes -conn $conn -EntityLogicalName $EntityLogicalName
 
            foreach($crmFieldKey in ($CrmRecord | Get-Member -MemberType NoteProperty).Name) {
 
                if(-not $crmFieldKey.EndsWith("_Property")) {
                    continue
                }
 
                $property = $CrmRecord.$crmFieldKey
 
                if($null -eq $property) {
                    continue
                }
 
                $attributeLogicalName = $property.Key
                $attributeValue = $property.Value
 
                if($CrmRecord.ReturnProperty_Id -eq $attributeValue -and -not $PreserveCrmRecordId) {
                    continue
                }
                                             
                $entity[$attributeLogicalName] = $attributeValue
            }
        }
        else {
         
            if([string]::IsNullOrEmpty($EntityLogicalName)) {
                 throw "EntityLogicalName is required."
            }
         
            if($null -eq $Fields) {
                throw "Fields is required."
            }
 
            $entity = New-Object Microsoft.Xrm.Sdk.Entity($EntityLogicalName)
 
            foreach($field in $Fields.GetEnumerator()) {
                $entity[$field.Key] = $field.Value
            }
        }
 
        $result = $conn.Create($entity)
 
        if($result -eq [System.Guid]::Empty) {
            throw "Create returned an empty Guid for entity '$EntityLogicalName'."
        }
 
        return $result
    }
    catch {
        throw
    }
}
 
function Get-CrmRecord{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml
    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1)]
        [string]$EntityLogicalName,
        [parameter(Mandatory=$true, Position=2)]
        [guid]$Id,
        [parameter(Mandatory=$true, Position=3)]
        [string[]]$Fields,
        [parameter(Mandatory=$false, Position=4)]
        [switch]$IncludeNullValue
    )
 
    $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))
         
    if($Fields -eq "*")
    {
        $columnSet = New-Object Microsoft.Xrm.Sdk.Query.ColumnSet($true)
    }
    else
    {
        $columnSet = New-Object Microsoft.Xrm.Sdk.Query.ColumnSet($Fields)
    }
 
    try
    {
        $record = $conn.Retrieve($EntityLogicalName, $Id, $columnSet)
    }
    catch
    {
        throw $_.Exception
    }
     
    if($record -eq $null)
    {
        throw $_.Exception
    }
         
    $psobj = @{ }
    $meta = Get-CrmEntityMetadata -conn $conn -EntityLogicalName $EntityLogicalName -EntityFilters Attributes
    if($IncludeNullValue)
    {
        if($Fields -eq "*")
        {
            # Add all fields first
            foreach($attName in $meta.Attributes)
            {
                if (-not $attName.IsValidForRead) { continue }
                $psobj[$attName.LogicalName] = $null
                $psobj["$($attName.LogicalName)_Property"] = $null
            }
        }
        else
        {
            foreach($attName in $Fields)
            {
                $psobj[$attName] = $null
                $psobj["$($attName)_Property"] = $null
            }
        }
    }
         
    foreach($att in $record.Attributes)
    {
        if($att.Value -is [Microsoft.Xrm.Sdk.EntityReference])
        {
            $psobj[$att.Key] = $att.Value.Name
        }
        elseif($att.Value -is [Microsoft.Xrm.Sdk.AliasedValue])
        {
            $psobj[$att.Key] = $att.Value.Value
        }
        else
        {
            $psobj[$att.Key] = $att.Value
        }
    }
    $psobj += @{
        original = $record
        logicalname = $EntityLogicalName
        EntityReference = New-CrmEntityReference -EntityLogicalName $EntityLogicalName -Id $Id
        ReturnProperty_EntityName = $EntityLogicalName
        ReturnProperty_Id = $record.($meta.PrimaryIdAttribute)
    }
     
    [PSCustomObject]$psobj
}
 
#Alias for Set-CrmRecord
New-Alias -Name Update-CrmRecord -Value Set-CrmRecord
 
#UpdateEntity
function Set-CrmRecord{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml
 
    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1, ParameterSetName="CrmRecord")]
        [PSObject]$CrmRecord,
        [parameter(Mandatory=$true, Position=1, ParameterSetName="Fields")]
        [string]$EntityLogicalName,
        [parameter(Mandatory=$true, Position=2, ParameterSetName="Fields")]
        [guid]$Id,
        [parameter(Mandatory=$true, Position=3, ParameterSetName="Fields")]
        [hashtable]$Fields,
        [parameter(Mandatory=$false)]
        [switch]$Upsert,
        [parameter(Mandatory=$false)]
        [AllowNull()]
        [AllowEmptyString()]
        [string]$PrimaryKeyField
    )
 
    $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))
 
    if($CrmRecord -ne $null)
    {
        $entityLogicalName = $CrmRecord.logicalname
    }
    else
    {
        $entityLogicalName = $EntityLogicalName
    }
 
    # 'PrimaryKeyField' is an options parameter and is used for custom activity entities
    if(-not [string]::IsNullOrEmpty($PrimaryKeyField))
    {
        $primaryKeyField = $PrimaryKeyField
    }
    else
    {
        $primaryKeyField = GuessPrimaryKeyField -EntityLogicalName $entityLogicalName
    }
 
    # If upsert specified
    if($Upsert)
    {
        $retrieveFields = New-Object System.Collections.Generic.List[string]
 
        if($CrmRecord -ne $null)
        {
             # when CrmRecord passed, assume this comes from other system.
            $id = $CrmRecord.$primaryKeyField
            foreach($crmFieldKey in ($CrmRecord | Get-Member -MemberType NoteProperty).Name)
            {
                if($crmFieldKey.EndsWith("_Property"))
                {
                    $retrieveFields.Add(($CrmRecord.$crmFieldKey).Key)
                }
                elseif(($crmFieldKey -eq "original") -or ($crmFieldKey -eq "logicalname") -or ($crmFieldKey -eq "EntityReference") -or ($crmFieldKey -like "ReturnProperty_*"))
                {
                    continue
                }
                else
                {
                    # to have original value, rather than formatted value, replace the value from original record.
                    $CrmRecord.$crmFieldKey = $CrmRecord.original[$crmFieldKey+"_Property"].Value
                }
            }
        }
        else
        {
            foreach($crmFieldKey in $Fields.Keys)
            {
                $retrieveFields.Add($crmFieldKey)
            }
        }
 
        $existingRecord = Get-CrmRecord -conn $conn -EntityLogicalName $entityLogicalName -Id $id -Fields $retrieveFields.ToArray() -ErrorAction SilentlyContinue
 
        if($existingRecord.original -eq $null)
        {
            if($CrmRecord -ne $null)
            {
                $Fields = @{}
 
                foreach($crmFieldKey in ($CrmRecord | Get-Member -MemberType NoteProperty).Name)
                {
                    if($crmFieldKey.EndsWith("_Property"))
                    {
                        $Fields.Add(($CrmRecord.$crmFieldKey).Key, ($CrmRecord.$crmFieldKey).Value)
                    }
                }
            }
 
            if($Fields[$primaryKeyField] -eq $null)
            {
                $Fields.Add($primaryKeyField, $Id)
            }
 
            $result = New-CrmRecord -conn $conn -EntityLogicalName $entityLogicalName -Fields $Fields
 
            return $result
        }
        else
        {
            if($CrmRecord -ne $null)
            {
                $CrmRecord.original = $existingRecord.original
            }
        }
    }
 
    if($CrmRecord -ne $null)
    {
        $originalRecord = $CrmRecord.original
        $Id = $originalRecord[$primaryKeyField]
    }
 
    $entity = New-Object Microsoft.Xrm.Sdk.Entity($entityLogicalName)
    $entity.Id = $Id
 
    if($CrmRecord -ne $null)
    {
        foreach($crmFieldKey in ($CrmRecord | Get-Member -MemberType NoteProperty).Name)
        {
            $crmFieldValue = $CrmRecord.$crmFieldKey
 
            if(($crmFieldKey -eq "original") -or ($crmFieldKey -eq "logicalname") -or ($crmFieldKey -eq "EntityReference") -or ($crmFieldKey -like "*_Property") -or ($crmFieldKey -like "ReturnProperty_*"))
            {
                continue
            }
            elseif($originalRecord[$crmFieldKey+"_Property"].Value -is [bool])
            {
                if($crmFieldValue -is [Int32])
                {
                    if(($originalRecord[$crmFieldKey+"_Property"].Value -and $crmFieldValue -eq 1) -or (!$originalRecord[$crmFieldKey+"_Property"].Value -and $crmFieldValue -eq 0))
                    {
                        continue
                    }
                }
                elseif($crmFieldValue -is [bool])
                {
                    if($crmFieldValue -eq $originalRecord[$crmFieldKey+"_Property"].Value)
                    {
                        continue
                    }
                }
                elseif($crmFieldValue -eq $originalRecord[$crmFieldKey])
                {
                    continue
                }
            }
            elseif($originalRecord[$crmFieldKey+"_Property"].Value -is [Microsoft.Xrm.Sdk.OptionSetValue])
            {
                if($crmFieldValue -is [Microsoft.Xrm.Sdk.OptionSetValue])
                {
                    if($crmFieldValue.Value -eq $originalRecord[$crmFieldKey+"_Property"].Value.Value)
                    {
                        continue
                    }
                }
                elseif($crmFieldValue -is [Int32])
                {
                    if($crmFieldValue -eq $originalRecord[$crmFieldKey+"_Property"].Value.Value)
                    {
                        continue
                    }
                }
                elseif($crmFieldValue -eq $originalRecord[$crmFieldKey])
                {
                    continue
                }
            }
            elseif($originalRecord[$crmFieldKey+"_Property"].Value -is [Microsoft.Xrm.Sdk.Money])
            {
                if($crmFieldValue -is [Microsoft.Xrm.Sdk.Money])
                {
                    if($crmFieldValue.Value -eq $originalRecord[$crmFieldKey+"_Property"].Value.Value)
                    {
                        continue
                    }
                }
                elseif($crmFieldValue -is [decimal] -or $crmFieldValue -is [Int32])
                {
                    if($crmFieldValue -eq $originalRecord[$crmFieldKey+"_Property"].Value.Value)
                    {
                        continue
                    }
                }
                elseif($crmFieldValue -eq $originalRecord[$crmFieldKey])
                {
                    continue
                }
            }
            elseif($originalRecord[$crmFieldKey+"_Property"].Value -is [Microsoft.Xrm.Sdk.EntityReference])
            {
                if(($crmFieldValue -is [Microsoft.Xrm.Sdk.EntityReference]) -and ($crmFieldValue.Id -eq $originalRecord[$crmFieldKey+"_Property"].Value.Id))
                {
                    continue
                }
                elseif($crmFieldValue -eq $originalRecord[$crmFieldKey])
                {
                    continue
                }
            }
            elseif($crmFieldValue -eq $originalRecord[$crmFieldKey])
            {
                continue
            }
 
            $value = $null
 
            if($crmFieldValue -eq $null)
            {
                $value = $null
            }
            else
            {
                if($CrmRecord.($crmFieldKey + "_Property") -ne $null)
                {
                    $type = $CrmRecord.($crmFieldKey + "_Property").Value.GetType().Name
                }
                else
                {
                    $type = $crmFieldValue.GetType().Name
                }
 
                switch($type)
                {
                    "Boolean" {
                        if($crmFieldValue -is [Boolean]) { $value = $crmFieldValue } else { $value = [Boolean]::Parse($crmFieldValue)}
                        break
                    }
                    "DateTime" {
                        if($crmFieldValue -is [DateTime]) { $value = $crmFieldValue } else { $value = [DateTime]::Parse($crmFieldValue) }
                        break
                    }
                    "Decimal" {
                        if($crmFieldValue -is [Decimal]) { $value = $crmFieldValue } else { $value = [Decimal]::Parse($crmFieldValue) }
                        break
                    }
                    "Single" {
                        if($crmFieldValue -is [Single]) { $value = $crmFieldValue } else { $value = [Single]::Parse($crmFieldValue) }
                        break
                    }
                    "Money" {
                        if($crmFieldValue -is [Microsoft.Xrm.Sdk.Money]) { $value = $crmFieldValue } else { $value = [Microsoft.Xrm.Sdk.Money]::new([decimal]$crmFieldValue) }
                        break
                    }
                    "Int32" {
                        if($crmFieldValue -is [Int32]) { $value = $crmFieldValue } else { $value = [Int32]::Parse($crmFieldValue) }
                        break
                    }
                    "EntityReference" {
                        $value = $crmFieldValue
                        break
                    }
                    "OptionSetValue" {
                        if($crmFieldValue -is [Microsoft.Xrm.Sdk.OptionSetValue]) { $value = $crmFieldValue } else { $value = [Microsoft.Xrm.Sdk.OptionSetValue]::new([Int32]$crmFieldValue) }
                        break
                    }
                    "String" {
                        $value = $crmFieldValue
                        break
                    }
                    default {
                        $value = $crmFieldValue
                        break
                    }
                }
            }
 
            $entity[$crmFieldKey] = $value
        }
    }
    else
    {
        foreach($field in $Fields.GetEnumerator())
        {
            $entity[$field.Key] = $field.Value
        }
    }
 
    try
    {
        if($entity.Attributes.Count -eq 0)
        {
            return
        }
 
        $conn.Update($entity)
    }
    catch
    {
        throw
    }
}
 
#DeleteEntity
function Remove-CrmRecord{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml
    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1, ParameterSetName="CrmRecord", ValueFromPipeline=$True)]
        [PSObject]$CrmRecord,
        [parameter(Mandatory=$true, Position=1, ParameterSetName="Fields")]
        [string]$EntityLogicalName,
        [parameter(Mandatory=$true, Position=2, ParameterSetName="Fields")]
        [guid]$Id
    )
 
    begin
    {
        $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))
    }
    process
    {
        if($CrmRecord -ne $null)
        {
            $EntityLogicalName = $CrmRecord.logicalname
            $Id = $CrmRecord.($EntityLogicalName + "id")
        }
 
        try
        {
            $result = $conn.Delete($EntityLogicalName, $Id)
            if(!$result)
            {
                throw $_.Exception
            }
        }
        catch
        {
            throw $_.Exception
        }
    }
}
 
function Get-CrmRecordsByFetch {
    # .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml
    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
 
        [parameter(Mandatory=$true, Position=1)]
        [string]$Fetch,
 
        [parameter(Mandatory=$false, Position=2)]
        [int]$TopCount,
 
        [parameter(Mandatory=$false, Position=3)]
        [int]$PageNumber,
 
        [parameter(Mandatory=$false, Position=4)]
        [string]$PageCookie,
 
        [parameter(Mandatory=$false, Position=5)]
        [switch]$AllRows
    )
 
    $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))
 
    if($null -eq $conn) {
        throw "Dataverse connection is null."
    }
 
    if($PageNumber -le 0) {
        $PageNumber = 1
    }
 
    if(-not $PageCookie) {
        $PageCookie = $null
    }
 
    $recordsList = New-Object "System.Collections.Generic.List[System.Management.Automation.PSObject]"
    $fetchQueryTime = New-TimeSpan -Seconds 0
    $crmFetchTimer = [System.Diagnostics.Stopwatch]::StartNew()
 
    $PagingCookie = $null
    $NextPage = $false
 
    try {
        [xml]$xml = $Fetch
 
        if($null -eq $xml.fetch) {
            throw "Invalid FetchXML. Root element must be <fetch>."
        }
 
        $entityNode = $xml.SelectSingleNode("/fetch/entity")
        if($null -eq $entityNode) {
            throw "Invalid FetchXML. FetchXML must contain a /fetch/entity node."
        }
 
        $logicalName = $entityNode.Name
 
        if($TopCount -eq 0 -and $xml.fetch.count) {
            $TopCount = [int]$xml.fetch.count
        }
 
        do {
            Write-Debug "Fetching page $PageNumber"
 
            $xml.fetch.SetAttribute("page", [string]$PageNumber)
 
            if($TopCount -gt 0) {
                $xml.fetch.SetAttribute("count", [string]$TopCount)
            }
 
            if(-not [string]::IsNullOrEmpty($PageCookie)) {
                $xml.fetch.SetAttribute("paging-cookie", $PageCookie)
            }
            else {
                if($xml.fetch.HasAttribute("paging-cookie")) {
                    $xml.fetch.RemoveAttribute("paging-cookie")
                }
            }
 
            $fetchXmlForPage = $xml.OuterXml
 
            $crmFetchTimer.Restart()
 
            $fetchExpression = New-Object Microsoft.Xrm.Sdk.Query.FetchExpression($fetchXmlForPage)
 
            $entityCollection = $conn.RetrieveMultiple($fetchExpression)
 
            $crmFetchTimer.Stop()
            $fetchQueryTime += $crmFetchTimer.Elapsed
 
            if($null -eq $entityCollection) {
                break
            }
 
            foreach($entity in $entityCollection.Entities) {
                $recordsList.Add((Convert-CrmEntityToPsObject -Entity $entity -LogicalName $logicalName))
            }
 
            $NextPage = [bool]$entityCollection.MoreRecords
            $PagingCookie = $entityCollection.PagingCookie
 
            if($NextPage) {
                $PageNumber++
                $PageCookie = $PagingCookie
            }
 
        } while ($NextPage -and $AllRows)
    }
    catch {
        Write-Error $_.Exception
        throw
    }
 
    $resultSet = New-Object 'System.Collections.Generic.Dictionary[[System.String],[System.Object]]'
 
    $resultSet.Add("CrmRecords", $recordsList)
    $resultSet.Add("Count", $recordsList.Count)
    $resultSet.Add("PagingCookie", $PagingCookie)
    $resultSet.Add("NextPage", $NextPage)
    $resultSet.Add("FetchXml", $Fetch)
    $resultSet.Add("FetchQueryTime", $fetchQueryTime)
 
    Write-Verbose "FetchQueryTime:$fetchQueryTime"
 
    return $resultSet
}
 
#UpdateStateAndStatusForEntity
function Set-CrmRecordState{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml
    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1, ParameterSetName="CrmRecord", ValueFromPipeline=$true)]
        [PSObject]$CrmRecord,
        [parameter(Mandatory=$true, Position=1, ParameterSetName="NameWithId")]
        [string]$EntityLogicalName,
        [parameter(Mandatory=$true, Position=2, ParameterSetName="NameWithId")]
        [guid]$Id,
        [parameter(Mandatory=$true, Position=3)]
        [string]$StateCode,
        [parameter(Mandatory=$true, Position=4)]
        [string]$StatusCode
    )
 
    begin
    {
        $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))
    }
 
    process
    {
        if($CrmRecord -ne $null)
        {
            $EntityLogicalName = $CrmRecord.logicalname
            #$Id = $CrmRecord.($EntityLogicalName + "id")
            $Id = $CrmRecord.'ReturnProperty_Id'
        }
 
        # Try to parse into int
        $StateCodeInt = 0
        $StatusCodeInt = 0
         
        try
        {
            if([int32]::TryParse($StateCode, [ref]$StateCodeInt) -and [int32]::TryParse($StatusCode, [ref]$StatusCodeInt))
            {
                $result = $conn.UpdateStateAndStatusForEntity($EntityLogicalName, $Id, $StateCodeInt, $statusCodeInt, [Guid]::Empty)
                if(!$result)
                {
                    throw $_.Exception
                }
            }
            else
            {
                $result = $conn.UpdateStateAndStatusForEntity($EntityLogicalName, $Id, $stateCode, $statusCode, [Guid]::Empty)
                if(!$result)
                {
                    throw $_.Exception
                }
            }
        }
        catch
        {
            throw $_.Exception
        }
    }
}
 
function Invoke-CrmAction {
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml
    [OutputType([hashtable])]
    [OutputType([Microsoft.Xrm.Sdk.OrganizationResponse], ParameterSetName="Raw")]
    param (
        [Microsoft.Xrm.Sdk.IOrganizationService]
        $conn,
 
        [Parameter(
            Position=1,
            Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Name,
 
        [Parameter(Position=2)]
        [hashtable]
        $Parameters,
 
        [Parameter(ValueFromPipeline, Position=3)]
        [ValidateNotNullOrEmpty()]
        [Microsoft.Xrm.Sdk.EntityReference]
        $Target,
 
        [Parameter(ParameterSetName="Raw")]
        [switch]
        $Raw
    )
    begin
    {
        $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))
    }
    process
    {
        $request = new-object Microsoft.Xrm.Sdk.OrganizationRequest
        $request.RequestName = $Name
        if($Target) {
            $request.Parameters.Add("Target", $Target)
        }
 
        if($Parameters) {
            foreach($parameter in $Parameters.GetEnumerator()) {
                $request.Parameters.Add($parameter.Name, $parameter.Value)
            }
        }
 
        try {
            $response = $conn.Execute($request)
         
            if($Raw) {
                Write-Output $response
            } elseif ($response.Results -and $response.Results.Count -gt 0) {
                $outputArguments = @{}
                foreach($outputArgument in $response.Results) {
                    $outputArguments.Add($outputArgument.Key, $outputArgument.Value)
                }
                Write-Output $outputArguments
            } else {
                Write-Output $null
            }
        }
        catch {
            Write-Error $_
        }
    }
}
 
function Get-CrmRecords{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml
 
    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1)][alias("EntityName")]
        [string]$EntityLogicalName,
        [parameter(Mandatory=$false, Position=2)][alias("FieldName")]
        [string]$FilterAttribute,
        [parameter(Mandatory=$false, Position=3)][alias("Op")]
        [ValidateSet('eq','neq','ne','gt','ge','le','lt','like','not-like','in','not-in','between','not-between','null','not-null','yesterday','today','tomorrow','last-seven-days','next-seven-days','last-week','this-week','next-week','last-month','this-month','next-month','on','on-or-before','on-or-after','last-year','this-year','next-year','last-x-hours','next-x-hours','last-x-days','next-x-days','last-x-weeks','next-x-weeks','last-x-months','next-x-months','olderthan-x-months','olderthan-x-years','olderthan-x-weeks','olderthan-x-days','olderthan-x-hours','olderthan-x-minutes','last-x-years','next-x-years','eq-userid','ne-userid','eq-userteams','eq-useroruserteams','eq-useroruserhierarchy','eq-useroruserhierarchyandteams','eq-businessid','ne-businessid','eq-userlanguage','this-fiscal-year','this-fiscal-period','next-fiscal-year','next-fiscal-period','last-fiscal-year','last-fiscal-period','last-x-fiscal-years','last-x-fiscal-periods','next-x-fiscal-years','next-x-fiscal-periods','in-fiscal-year','in-fiscal-period','in-fiscal-period-and-year','in-or-before-fiscal-period-and-year','in-or-after-fiscal-period-and-year','begins-with','not-begin-with','ends-with','not-end-with','under','eq-or-under','not-under','above','eq-or-above')]
        [string]$FilterOperator,
        [parameter(Mandatory=$false, Position=4)][alias("Value", "FieldValue")]
        [string]$FilterValue,
        [parameter(Mandatory=$false, Position=5)]
        [string[]]$Fields,
        [parameter(Mandatory=$false, Position=6)]
        [switch]$AllRows,
        [parameter(Mandatory=$false, Position=7)]
        [int]$TopCount
    )
    $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))
 
    if($FilterOperator -and $FilterOperator.StartsWith("-"))
    {
        $FilterOperator = $FilterOperator.Remove(0, 1)
    }
    if( !($EntityLogicalName -cmatch "^[a-z_]*$") )
    {
        $EntityLogicalName = $EntityLogicalName.ToLower()
        Write-Verbose "EntityLogicalName contains uppercase which isn't possible in CRM, overwritting with ToLower() new value: $EntityLogicalName"
    }
 
    if( ($Fields -eq "*") -OR ($Fields -eq "%") )
    {
        Write-Verbose 'PERFORMANCE: All attributes were requested'
        $fetchAttributes = "<all-attributes/>"
    }
    elseif ($Fields)
    {
        foreach($Field in $Fields)
        {
            if($field -ne $null){
                $fetchAttributes += "<attribute name='{0}' />" -F $Field
            }
        }
    }
    else
    {
        #lookup the primary attribute
        $primaryAttribute = $conn.GetEntityMetadata($EntityLogicalName.ToLower()).PrimaryIdAttribute
        $fetchAttributes = "<attribute name='{0}' />" -F $primaryAttribute
    }
 
    #if any of the values are missing, but they're not *ALL* missing
    if(
        ($FilterAttribute -and !$FilterOperator) -or
        (!$FilterAttribute -and $FilterOperator) -or
        ($FilterValue -and (!$FilterOperator -or !$FilterAttribute))
    ){
        #TODO: convert this to a parameter set to avoid this extra logic
        Write-Error "One of the `$FilterAttribute `$FilterOperator `$FilterValue parameters is empty, to query all records exclude all filter parameters."
        return
    }
     
    if($FilterAttribute -and $FilterOperator -and $FilterValue)
    {
        # Escape XML charactors
        $FilterValue = [System.Security.SecurityElement]::Escape($FilterValue)
        Write-Verbose "Using the supplied single filter of $FilterAttribute '$FilterOperator' $FilterValue"
        $fetch =
@"
    <fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false" no-lock="true">
        <entity name="{0}">
            {1}
            <filter type='and'>
                <condition attribute='{2}' operator='{3}' value='{4}' />
            </filter>
        </entity>
    </fetch>
"@
    }
    elseif($FilterAttribute -and $FilterOperator){
         # Escape XML charactors
        $FilterValue = [System.Security.SecurityElement]::Escape($FilterValue)
        Write-Verbose "Using the supplied single filter of $FilterAttribute '$FilterOperator' and NO value"
        $fetch =
@"
    <fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false" no-lock="true">
        <entity name="{0}">
            {1}
            <filter type='and'>
                <condition attribute='{2}' operator='{3}' />
            </filter>
        </entity>
    </fetch>
"@
    }
    else
    {
        Write-Verbose "PERFORMANCE: `$FilterAttribute `$FilterOperator `$FilterValue were not supplied, fetching all records with NO filter."
        $fetch =
@"
    <fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false" no-lock="true">
        <entity name="{0}">
            {1}
        </entity>
    </fetch>
"@
    }
    $fetch = $fetch -F $EntityLogicalName, $fetchAttributes, $FilterAttribute, $FilterOperator, $FilterValue
     
    if($AllRows)
    {
        Write-Verbose "PERFORMANCE: All rows were requested instead of the first 5000"
        $results = Get-CrmRecordsByFetch -conn $conn -Fetch $fetch -AllRows
    }
    else
    {
        $results = Get-CrmRecordsByFetch -conn $conn -Fetch $fetch -TopCount $TopCount
    }
     
    return $results
}
 
function Get-CrmRecordsByViewName{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml
 
    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1)]
        [string]$ViewName,
        [parameter(Mandatory=$false, Position=2)]
        [bool]$IsUserView,
        [parameter(Mandatory=$false, Position=3)]
        [switch]$AllRows,
        [parameter(Mandatory=$false, Position=4)]
        [int]$TopCount
    )
 
    $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))
     
    # Escape XML charactor
    $ViewName = [System.Security.SecurityElement]::Escape($ViewName)
 
    if($IsUserView)
    {
        $fetch = @"
    <fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false" no-lock="true">
        <entity name="userquery">
            <attribute name="fetchxml" />
            <filter type='and'>
                <condition attribute='name' operator='eq' value='{0}' />
            </filter>
        </entity>
    </fetch>
"@
    }
    else
    {
        $fetch = @"
    <fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false" no-lock="true">
        <entity name="savedquery">
            <attribute name="fetchxml" />
            <filter type='and'>
                <condition attribute='name' operator='eq' value='{0}' />
            </filter>
        </entity>
    </fetch>
"@
    }
 
    $fetch = $fetch -F $ViewName
    #get the views matching the search phrase
    $views = Get-CrmRecordsByFetch -conn $conn -Fetch $fetch
 
    if($views.CrmRecords.Count -eq 0)
    {
        Write-Warning "Couldn't find the view"
        break
    }
    if($AllRows)
    {
        $results = Get-CrmRecordsByFetch -conn $conn -Fetch $views.CrmRecords[0].fetchxml -AllRows
    }
    else
    {
        $results = Get-CrmRecordsByFetch -conn $conn -Fetch $views.CrmRecords[0].fetchxml -TopCount $TopCount
    }
    return $results
}
 
function Get-CrmRecordsCount{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml
 
    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1)][alias("EntityName")]
        [string]$EntityLogicalName
    )
    $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))
    $fetch =
@"
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false" no-lock="true">
    <entity name="{0}">
        <attribute name='{1}' />
    </entity>
</fetch>
"@
     
    if($EntityLogicalName -eq "usersettings")
    {
        $PrimaryKeyField = "systemuserid"
    }
    else
    {
        $PrimaryKeyField = "$EntityLogicalName`id"
    }
    $fetch = $fetch -F $EntityLogicalName, $PrimaryKeyField
     
    $results = Get-CrmRecordsByFetch -conn $conn -Fetch $fetch -AllRows
         
    return $results.Count
}