Closed raph91 closed 1 year ago
Hi @raph91 - Set-CrmRecord will execute an update to the record regardless of what is supplied (you can even supply the same exact value with zero changes and it will set the change).
Here is an example:
$accounts=get-crmrecords -EntityLogicalName account -TopCount 5 -Fields name
$accounts.CrmRecords[0].name
$accounts.CrmRecords[0].accountid
$accounts.CrmRecords[0].name
--Update the account using the accountid and the current (identical) name
Set-CrmRecord -EntityLogicalName account -Id $accounts.CrmRecords[0].accountid -Fields @{"name"=$accounts.CrmRecords[0].name}
Now, as a test, let's change it using a different letter case (toUpper will turn it all caps). Then we'll re-retrieve the same exact record and read back the value to show any changes:
write-host "Currrent value:"
$accounts.CrmRecords[0].name
Write-host "change the value to: $($accounts.CrmRecords[0].name.ToUpper())"
Set-CrmRecord -EntityLogicalName account -Id $accounts.CrmRecords[0].accountid -Fields @{"name"=$accounts.CrmRecords[0].name.ToUpper()}
$changedRecord=get-crmrecord -EntityLogicalName account -Id $accounts.CrmRecords[0].accountid -Fields name
Write-Host "new value"
$changedRecord.name
Hi @seanmcne
Interesting. I can confirm your steps, but my issue lies within the behavior of "Set-CrmRecord $accounts.CrmRecords[0]". When I pass the object and not specifying the entity/id, it doesn't update the field.
I think I do not need to explain your own implementation, but I add the screenshots from the Set-CrmRecords help to show what I mean:
First with defining entity and id:
Write-Host $accounts.CrmRecords[0].accountid
Write-Host "Current value:" $accounts.CrmRecords[0].name " (accountid:" $accounts.CrmRecords[0].accountid ")"
$accounts.CrmRecords[0].name = "pArEnT aCcOuNt NaMe"
Write-Host "New value:" $accounts.CrmRecords[0].name " (accountid:" $accounts.CrmRecords[0].accountid ")"
Set-CrmRecord -EntityLogicalName account -Id $accounts.CrmRecords[0].accountid -Fields @{"name" = $accounts.CrmRecords[0].name }
$updatedAccount = Get-CrmRecord -EntityLogicalName account -Id $accounts.CrmRecords[0].accountid -Fields name
Write-Host $updatedAccount.name
Output (working):
Write-Host $accounts.CrmRecords[0].accountid
Write-Host "Current value:" $accounts.CrmRecords[0].name " (accountid:" $accounts.CrmRecords[0].accountid ")"
$accounts.CrmRecords[0].name = "PaReNt aCcOuNt NaMe"
Write-Host "New value:" $accounts.CrmRecords[0].name " (accountid:" $accounts.CrmRecords[0].accountid ")"
Set-CrmRecord $accounts.CrmRecords[0]
$updatedAccount = Get-CrmRecord -EntityLogicalName account -Id $accounts.CrmRecords[0].accountid -Fields name
Write-Host $updatedAccount.name
Output (not working):
Interesstingly enough, I tried to do the same steps as described in the help, Example 4, with the same behavior:
$account = Get-CrmRecord account 9620cf26-b091-ed11-b818-00155d0105da name
Write-Host "Old name:" $account.name
$account.name = "Parent Account Name"
Write-Host "New name:" $account.name
Set-CrmRecord $account
$newaccount = Get-CrmRecord account 9620cf26-b091-ed11-b818-00155d0105da name
Write-Host "Updated name:" $newaccount.name
It really does only work when the new value has different characters:
Did I miss something?
Thank you.
Ok thanks for clarifying the situation. When CrmRecord is used, each property on the record is compared to the original in this code: https://github.com/seanmcne/Microsoft.Xrm.Data.PowerShell/blob/2c671af6d86288d14aa29e73a2d992a8913d7e7f/Microsoft.Xrm.Data.PowerShell/Microsoft.Xrm.Data.PowerShell.psm1#L744C1-L745C1
For anything which isn't a special type (which would be string, or anything that isn't specifically handled) the function does the following check to detect a difference between the two object attribute values:
$crmFieldValue -eq $originalRecord[$crmFieldKey]
It doesn't assume a string, per se, so it's just trying to see if the two object properties are equal. looking at the operator documentation from powershell -eq is insensitive and -ceq is case sensitive: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comparison_operators?view=powershell-7.2#common-features
When set-crmrecord (update) is executed with the properties provodied directly there isn't any additional logic executed and whatever is provided gets sent to the API. However, when passing in an object/crmRecord there has to be several assumptions made when checking for 'what was updated' to ensure changed attributes are detected and today that logic uses an equals check.
The technical reason the update with only a case change doesn't process the difference is due to poweshell's default string comparison, when using -eq against a string it uses a case insensitive equality comparison whereas an operator like -ceq forced case sensitivity. One possible option would be to change it over to -ceq, however the -eq attribute check isn't specific to an attribute type and I think it's possible there could be some unintended consequences.
I think I can see few ways forward for this:
Thank you for the clarification, makes sense to me. I think I will stick to way 1! I appreciate your help, thank you again.
Hi
I am trying to update records in dynamics 365 with Set-CrmRecord (account table). I think "Set-CrmRecord" is not case sensitive, means that if the same string is available but with another spelling, it does not update the field.
Example: Dynamics 365 field value: CoMpany1 Source field value: Company1
I can successfully update the record, but when I get it again (either with Get-CrmRecord or Get-CrmRecordsByFetch), the old value is still set. When I change the source field value to Company2, the Dynamics 365 field value changes correctly to "Company2".
So I assume "Set-CrmRecord" doesn't care about the spelling/case sensitivity and does not update the record, if the characters are equal. Could that be the case?
Thank you