We had mapped the primary field for deletion and the package was also showing success.
However back in our CRM / Sales Hub app, we saw that none of the records were deleted (total – 48999)
The reason it was showing success is that we had specified the Ignore Error option in our CDS Destination component.
Then we created 2 more records but didn’t specify the partition ID for them.
This time on the successful run of the package we can see those 2 new records getting deleted for which we didn’t specify any partition ID i.e. Test 1 and Test 2 records were deleted successfully.
If we check the Microsoft docs it mentions that we need to include the partition ID using the alternate key to delete those records using the DeleteMultiple request.
Could not find a way to specify an Alternate Key in the CDS Destination component for the Delete message and if we try deleting the records one by one instead of using the DeleteMultiple request we get the below error.
[CDS Destination [2]] Error: An error occurred with the following error message: “System.Exception: Error(s) occurred when processing the batch: [1] KingswaySoft.IntegrationToolkit.DynamicsCrm.WebAPI.WebApiServiceException: The remote server returned an error: (404) Not Found. (Error Type / Reason: NotFound, Detailed Message: {“error”:{“code”:”0x80040217″,”message”:”The HTTP status code of the response was not expected (404).\n\nStatus: 404\nResponse: \n{\”error\”:{\”message\”:\”Could not find item ‘b3a70971-9674-ef11-a671-6045bdfe58ee’.\”,\”details\”:[{\”message\”:\”\\r\\nErrors : [\\r\\n \\\”Resource Not Found. Learn more: https://aka.ms/cosmosdb-tsg-not-found\\\”\\r\\n]\\r\\n\”}]}}”}}) (SSIS Integration Toolkit for Microsoft Dynamics 365, v23.2.2.32701 – DtsDebugHost, v16.0.5270.0)System.Net.WebException
As expected, using CrmServiceClient also if we do not include partitionid we will get the below error for the records that have partition id specified.
The HTTP status code of the response was not expected (404).
Response:
{“error”:{“message”:”Could not find item ‘b3a70971-9674-ef11-a671-6045bdfe58ee’.”,”details”:[{“message”:”\r\nErrors : [\r\n \”Resource Not Found. Learn more: https://aka.ms/cosmosdb-tsg-not-found\”\r\n]\r\n”}]}}
Here we can specify the partitionId parameter to delete those records having the partitionId specified in the DeleteRequest
For DeleteMultiple Request we need to provide the alternate key as shown below.
We will have the alternate key auto-created by the system when we create an elastic table.
Sample Code –
var myServiceClient = new CrmServiceClient(connectionString);
var query = new QueryExpression("custom_myelastictable");
query.ColumnSet.AddColumns("custom_name", "partitionid");
var myElasticTableCollection = myServiceClient.RetrieveMultiple(query);
var lstEntityRefCollection = new EntityReferenceCollection();
// Delete Request
foreach (var elasticTable in myElasticTableCollection.Entities)
{
var deleteRequest = new DeleteRequest();
deleteRequest.Target = new EntityReference("custom_myelastictable", elasticTable.Id);
deleteRequest.Parameters["partitionId"] = elasticTable.Attributes["partitionid"];
var response = myServiceClient.Execute(deleteRequest);
}
// DeleteMultiple Request
foreach (var elasticTable in myElasticTableCollection.Entities)
{
var entityRef = new EntityReference("custom_myelastictable", elasticTable.Id);
entityRef.KeyAttributes.Add("custom_myelastictableid", elasticTable.Id);
entityRef.KeyAttributes.Add("partitionid", elasticTable.Attributes["partitionid"]);
lstEntityRefCollection.Add(entityRef);
}
var deleteMultipleRequest = new OrganizationRequest();
deleteMultipleRequest.RequestName = "DeleteMultiple";
deleteMultipleRequest.Parameters.Add("Targets", lstEntityRefCollection);
myServiceClient.Execute(deleteMultipleRequest);
We might get this error while trying to update one of the records.
Exception Message: EntityState must be set to null, Created (for Create message) or Changed (for Update message).
EntityState of primaryEntity: Unchanged, RequestName: Update
ErrorCode: -2147220989
The erroroccurs when OrganizationServiceContext tries to update an entity that has not been marked as modified. The EntityState remains Unchanged, and Dataverse expects it to be Changed or null for update operations.
OrganizationServiceContext automatically tracks entities’ states. When we retrieve an entity, it is set to Unchanged by default.
If we modify the entity without informing the context (e.g., using UpdateObject()), the context still thinks the entity is Unchanged, leading to this error during the update process.
This error typically happens within OrganizationServiceContext since it relies on internal state-tracking mechanisms, with IOrganizationService (e.g., Retrieve or RetrieveMultiple), we typically don’t run into this error because entities retrieved via IOrganizationService aren’t tracked in the same way.
There are 2 ways to resolve this error.
Use UpdateObject, it explicitly tells the context that the entity has been changed followed by SaveChanges() to commit the changes.
2. Create a new Entity object for update.
Sample Code –
if (myServiceClient.IsReady)
{
using (var context = new OrganizationServiceContext(myServiceClient))
{
// Retrieve leads where the 'lastname' contains 'Test'
var leadColl = from lead in context.CreateQuery("lead")
where lead.GetAttributeValue<string>("lastname").Contains("Test")
select lead;
// use Update Object
foreach (var lead in leadColl)
{
lead.Attributes["subject"] = "Updated Subject" + DateTime.Now.ToLongTimeString();
context.UpdateObject(lead);
context.SaveChanges();
}
// or create a new Entity object
foreach (var lead in leadColl)
{
Entity leadToUpdate = new Entity("lead", lead.Id)
{
["subject"] = "Updated Subject" + DateTime.Now.ToLongTimeString()
};
myServiceClient.Update(leadToUpdate);
}
}
}
In one of our requirements, we wanted to create/send an email on the creation/update of the case with the description of the email same as the description of the case.
In our Case record, for the description, we have the line break (\n) specified.
However, for the email created, we see the line break ignored.
To fix this we might think of applying the below formula by replacing “\n” with “”.
Here to get the active stage ID, open the business process flow and get its Guid.
Then using the awesome SQL4CDS XrmToolBox plugin get the Guid of the particular stage.
function OnLoad(executionContext)
{
var formContext = executionContext.getFormContext();
formContext.data.process.addOnStageChange(CheckStageAndToggleFieldBPF);
CheckStageAndToggleFieldBPF(executionContext);
}
function CheckStageAndToggleFieldBPF(executionContext) {
var formContext = executionContext.getFormContext();
var activeStage = formContext.data.process.getActiveStage();
var activeStageId = activeStage.getId();
var stagePropose = "3a275c22-fc45-4e89-97fc-41e5ec578743";
if (activeStageId.toLowerCase() === stagePropose) {
formContext.getControl("header_process_identifypursuitteam").setDisabled(false);
}
else {
formContext.getControl("header_process_identifypursuitteam").setDisabled(true);
}
}
select processidname,stagename, processstageid from processstage
where processid = '919E14D1-6489-4852-ABD0-A63A6ECAAC5D'
Also if we have the same fields used in multiple places / stages in the Business Process Flow, we will have the suffix added to the fields, so we need to refer the field appropriately in our script.
With the Associated Grid Control we can configure and show up four subgrids in the form, making it a more intuitive and cleaner form layout, with ease of navigation.
Below we are adding the Associated Grid Control component to the Contact’s form.
Here we have specified the Subgrid Tables and Views to begin with.
For the 1st subgrid specified we can set the specific options from the properties pane. Here let us try checking the Show related rows properties for the cases subgrid.
On doing so, we get the below message.
It basically reset the 1st subgrid’s table to Accounts from Case, the rest of the configuration remains unchanged.
Let us change it back to Cases and select the appropriate view.
Let us save and publish the change.
Now in the Contact form we can see the grid control with 4 different subgrids as configured.
The Active Cases shows the associated cases.
However, that is not the case with other subgrids as they show all the records.
To filter it to show the associated records we need to specify the relationship name while configuring the component.
Let us edit the component.
Below we specified the relationship name for the subgrid 2 i.e Accounts.
As expected, this time we can see Active Accounts filtered to show only those account records where the contact is associated as the primary contact.