Public/CRUD.ps1

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'))

    try {
        if($null -ne $CrmRecord) {
            $EntityLogicalName = $CrmRecord.ReturnProperty_EntityName

            if([string]::IsNullOrWhiteSpace($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
            }

            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([string]::IsNullOrWhiteSpace($attributeLogicalName)) {
                    continue
                }

                if($CrmRecord.ReturnProperty_Id -eq $attributeValue -and -not $PreserveCrmRecordId) {
                    continue
                }

                $entity[$attributeLogicalName] = $attributeValue
            }
        }
        else {
            if([string]::IsNullOrWhiteSpace($EntityLogicalName)) {
                throw "EntityLogicalName is required."
            }

            if($null -eq $Fields) {
                throw "Fields is required."
            }

            $entity = New-Object Microsoft.Xrm.Sdk.Entity($EntityLogicalName)
            $primaryKeyField = GuessPrimaryKeyField -EntityLogicalName $EntityLogicalName

            foreach($field in $Fields.GetEnumerator()) {
                if($field.Key -eq $primaryKeyField) {
                    if($null -ne $field.Value -and $field.Value -ne [Guid]::Empty) {
                        $entity.Id = [Guid]$field.Value
                    }
                    continue
                }

                $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
    }

    if($null -eq $record) {
        throw "Record '$EntityLogicalName' with Id '$Id' was not found."
    }

    $meta = Get-CrmEntityMetadata -conn $conn -EntityLogicalName $EntityLogicalName -EntityFilters Attributes
    $psobj = @{}

    if($IncludeNullValue) {
        if($Fields -eq "*") {
            foreach($att in $meta.Attributes) {
                if(-not $att.IsValidForRead) { continue }
                $psobj[$att.LogicalName] = $null
                $psobj["$($att.LogicalName)_Property"] = $null
            }
        }
        else {
            foreach($attName in $Fields) {
                $psobj[$attName] = $null
                $psobj["$($attName)_Property"] = $null
            }
        }
    }

    foreach($att in $record.Attributes.GetEnumerator()) {
        $property = [PSCustomObject]@{
            Key   = $att.Key
            Value = $att.Value
        }

        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
            $property.Value = $att.Value.Value
        }
        else {
            $psobj[$att.Key] = $att.Value
        }

        $psobj["$($att.Key)_Property"] = $property
    }

    foreach($formatted in $record.FormattedValues.GetEnumerator()) {
        if(-not $psobj.ContainsKey($formatted.Key)) {
            $psobj[$formatted.Key] = $formatted.Value
        }
        $psobj["$($formatted.Key)_FormattedValue"] = $formatted.Value
    }

    $psobj += @{
        original = $record
        logicalname = $EntityLogicalName
        EntityReference = New-CrmEntityReference -EntityLogicalName $EntityLogicalName -Id $Id
        ReturnProperty_EntityName = $EntityLogicalName
        ReturnProperty_Id = $record.Id
    }

    [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
    }

    if(-not [string]::IsNullOrEmpty($PrimaryKeyField)) {
        $primaryKeyField = $PrimaryKeyField
    }
    else {
        $primaryKeyField = GuessPrimaryKeyField -EntityLogicalName $entityLogicalName
    }

    if($Upsert) {
        $retrieveFields = New-Object System.Collections.Generic.List[string]

        if($CrmRecord -ne $null) {
            $id = $CrmRecord.$primaryKeyField
            if($null -eq $id) { $id = $CrmRecord.ReturnProperty_Id }

            foreach($crmFieldKey in ($CrmRecord | Get-Member -MemberType NoteProperty).Name) {
                if($crmFieldKey.EndsWith("_Property")) {
                    $retrieveFields.Add(($CrmRecord.$crmFieldKey).Key)
                }
            }
        }
        else {
            $id = $Id
            foreach($crmFieldKey in $Fields.Keys) {
                $retrieveFields.Add($crmFieldKey)
            }
        }

        $existingRecord = Get-CrmRecord -conn $conn -EntityLogicalName $entityLogicalName -Id $id -Fields $retrieveFields.ToArray() -ErrorAction SilentlyContinue

        if($null -eq $existingRecord -or $null -eq $existingRecord.original) {
            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)
            }

            return New-CrmRecord -conn $conn -EntityLogicalName $entityLogicalName -Fields $Fields
        }
        else {
            if($CrmRecord -ne $null) {
                $CrmRecord.original = $existingRecord.original
            }
        }
    }

    if($CrmRecord -ne $null) {
        $Id = $CrmRecord.ReturnProperty_Id
        if($null -eq $Id -and $CrmRecord.original -ne $null) {
            $Id = $CrmRecord.original.Id
        }
    }

    $entity = New-Object Microsoft.Xrm.Sdk.Entity($entityLogicalName)
    $entity.Id = $Id

    if($CrmRecord -ne $null) {
        foreach($crmFieldKey in ($CrmRecord | Get-Member -MemberType NoteProperty).Name) {
            if(($crmFieldKey -eq "original") -or ($crmFieldKey -eq "logicalname") -or ($crmFieldKey -eq "EntityReference") -or ($crmFieldKey -like "*_Property") -or ($crmFieldKey -like "*_FormattedValue") -or ($crmFieldKey -like "ReturnProperty_*")) {
                continue
            }

            $crmFieldValue = $CrmRecord.$crmFieldKey
            $propertyName = $crmFieldKey + "_Property"
            $originalValue = $null

            if($CrmRecord.PSObject.Properties.Name -contains $propertyName -and $null -ne $CrmRecord.$propertyName) {
                $originalValue = $CrmRecord.$propertyName.Value
            }

            if(Test-CrmValuesEquivalent -CurrentValue $crmFieldValue -OriginalValue $originalValue) {
                continue
            }

            $entity[$crmFieldKey] = Convert-CrmValueForSdk -Value $crmFieldValue -OriginalValue $originalValue
        }
    }
    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 {
        VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))
    }
    process {
        if($CrmRecord -ne $null) {
            $EntityLogicalName = $CrmRecord.logicalname
            $Id = $CrmRecord.ReturnProperty_Id
            if($null -eq $Id) { $Id = $CrmRecord.($EntityLogicalName + "id") }
        }

        try {
            $conn.Delete($EntityLogicalName, $Id)
        }
        catch {
            throw
        }
    }
}

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
    )

    VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))

    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.GetAttribute("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.'ReturnProperty_Id'
        }

        try {
            $StateCodeInt = 0
            $StatusCodeInt = 0

            if([int32]::TryParse($StateCode, [ref]$StateCodeInt) -and [int32]::TryParse($StatusCode, [ref]$StatusCodeInt)) {
                $stateValue = $StateCodeInt
                $statusValue = $StatusCodeInt
            }
            else {
                $stateValue = [int]$StateCode
                $statusValue = [int]$StatusCode
            }

            $entity = New-Object Microsoft.Xrm.Sdk.Entity($EntityLogicalName)
            $entity.Id = $Id
            $entity["statecode"] = New-Object Microsoft.Xrm.Sdk.OptionSetValue($stateValue)
            $entity["statuscode"] = New-Object Microsoft.Xrm.Sdk.OptionSetValue($statusValue)
            $conn.Update($entity)
        }
        catch {
            throw
        }
    }
}

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.GetEnumerator()) {
                    $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 is not valid in Dataverse logical names. New value: $EntityLogicalName"
    }

    if( ($Fields -eq "*") -OR ($Fields -eq "%") ) {
        Write-Verbose 'PERFORMANCE: All attributes were requested'
        $fetchAttributes = "<all-attributes/>"
    }
    elseif ($Fields) {
        $fetchAttributes = ""
        foreach($Field in $Fields) {
            if($field -ne $null) {
                $fetchAttributes += "<attribute name='{0}' />" -F $Field
            }
        }
    }
    else {
        $primaryAttribute = Get-CrmPrimaryIdAttribute -conn $conn -EntityLogicalName $EntityLogicalName
        $fetchAttributes = "<attribute name='{0}' />" -F $primaryAttribute
    }

    if(
        ($FilterAttribute -and !$FilterOperator) -or
        (!$FilterAttribute -and $FilterOperator) -or
        ($FilterValue -and (!$FilterOperator -or !$FilterAttribute))
    ) {
        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) {
        $FilterValue = [System.Security.SecurityElement]::Escape($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) {
        $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 {
        $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) {
        return Get-CrmRecordsByFetch -conn $conn -Fetch $fetch -AllRows
    }

    return Get-CrmRecordsByFetch -conn $conn -Fetch $fetch -TopCount $TopCount
}

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'))
    $ViewName = [System.Security.SecurityElement]::Escape($ViewName)

    if($IsUserView) {
        $viewEntityName = "userquery"
    }
    else {
        $viewEntityName = "savedquery"
    }

    $fetch = @"
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false" no-lock="true">
  <entity name="$viewEntityName">
    <attribute name="fetchxml" />
    <filter type="and">
      <condition attribute="name" operator="eq" value="{0}" />
    </filter>
  </entity>
</fetch>
"@
 -F $ViewName

    $views = Get-CrmRecordsByFetch -conn $conn -Fetch $fetch

    if($views.CrmRecords.Count -eq 0) {
        Write-Warning "Couldn't find the view"
        return
    }

    if($AllRows) {
        return Get-CrmRecordsByFetch -conn $conn -Fetch $views.CrmRecords[0].fetchxml -AllRows
    }

    return Get-CrmRecordsByFetch -conn $conn -Fetch $views.CrmRecords[0].fetchxml -TopCount $TopCount
}

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'))

    if($EntityLogicalName -eq "usersettings") {
        $PrimaryKeyField = "systemuserid"
    }
    else {
        $PrimaryKeyField = Get-CrmPrimaryIdAttribute -conn $conn -EntityLogicalName $EntityLogicalName
    }

    $fetch = @"
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false" no-lock="true">
  <entity name="{0}">
    <attribute name="{1}" />
  </entity>
</fetch>
"@
 -F $EntityLogicalName, $PrimaryKeyField

    $results = Get-CrmRecordsByFetch -conn $conn -Fetch $fetch -AllRows
    return $results.Count
}