Public/Set-AzTableAPIEntity.ps1

function Set-AzTableAPIEntity {
    <#
    .SYNOPSIS
        Inserts or replaces (upsert) an entity in Azure Table Storage.

    .DESCRIPTION
        Performs an HTTP PUT which replaces the entire entity if it already exists,
        or inserts it if it does not. All properties not included in the Entity
        parameter will be removed from an existing entity.

        Use Update-AzTableAPIEntity for a merge (PATCH) that preserves
        properties not present in the supplied entity.

    .PARAMETER Context
        Connection context created by New-AzTableAPIContext.

    .PARAMETER TableName
        Name of the target table.

    .PARAMETER Entity
        Hashtable or PSCustomObject representing the entity to insert or replace.
        Must include PartitionKey and RowKey properties.

    .PARAMETER ETag
        Optional ETag for optimistic concurrency. When specified the request is sent
        with an If-Match header, so the replace only succeeds if the entity exists
        and (unless '*' is used) its ETag matches. When omitted, the operation is an
        unconditional insert-or-replace (upsert).

    .PARAMETER PassThru
        When specified, returns a PSCustomObject containing the ETag returned by the
        service. Useful for subsequent optimistic-concurrency operations.

    .EXAMPLE
        $entity = @{ PartitionKey = 'Sales'; RowKey = '001'; Amount = 150.00 }
        Set-AzTableAPIEntity -Context $ctx -TableName 'Orders' -Entity $entity

    .EXAMPLE
        $result = Set-AzTableAPIEntity -Context $ctx -TableName 'Orders' -Entity $entity -PassThru
        $result.ETag
    #>

    [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')]
    [OutputType([PSCustomObject])]
    param (
        [Parameter(Mandatory)]
        [ValidateScript({
            ($_.PSObject.Properties.Name -contains 'Endpoint') -and
            ($_.PSObject.Properties.Name -contains 'AuthType')
        }, ErrorMessage = 'The -Context parameter requires a context object created by New-AzTableAPIContext.')]
        [PSCustomObject]$Context,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$TableName,

        [Parameter(Mandatory)]
        [ValidateNotNull()]
        [object]$Entity,

        [string]$ETag,

        [switch]$PassThru
    )

    $entityKeys = Get-AzTableEntityKey -Entity $Entity
    $pk = $entityKeys.PartitionKey
    $rk = $entityKeys.RowKey
    $resource = Format-AzTableEntityResource -TableName $TableName -PartitionKey $pk -RowKey $rk

    if ($PSCmdlet.ShouldProcess("$TableName / PartitionKey='$pk', RowKey='$rk'", 'Set entity in Azure Table Storage')) {
        try {
            # No If-Match header by default: a PUT without If-Match is an
            # insert-or-replace (upsert). Sending 'If-Match: *' would make the
            # request fail with 404 when the entity does not exist yet.
            $response = Invoke-AzTableRestMethod -Context $Context -Method 'PUT' -Resource $resource -Body $Entity -ETag $ETag
        } catch {
            $PSCmdlet.WriteError($_)
            return
        }

        if ($PassThru) {
            $responseETag = $response.Headers['ETag']
            if ($responseETag -is [array]) { $responseETag = $responseETag[0] }
            return [PSCustomObject]@{ ETag = $responseETag }
        }
    }
}