Archive
Power Apps | CDS | Track deleted records using ‘Change Tracking’
For unversed, Change Tracking in CDS allows data to be synchronized by detecting what data has changed since the data was initially extracted or last synchronized.
Its useful in Integration scenarios, where you have to keep data between CDS and external systems in sync.
Assume that your customer has a LOB application along with CDS and you want sync the LOB application (i.e., When record gets Created/Updated/Deleted in CDS), this can be achieved using ‘Change Tracking’ feature.
In this article, lets understand how ‘Change Tracking’ works in CDS using ‘Organization Service’, to:
- Get the Created or Updated records from last sync.
- Get Deleted records from last sync.
Enabling Change Tracking for an Entity:
- To use ‘Change Tracking’ make sure that the change tracking feature is enabled for that entity.
- This feature can be enabled by using the customization user interface.

‘Change Tracking’ using the Organization Service:
- When change tracking is enabled for an entity, RetrieveEntityChangesRequest message can be used to retrieve the changes for that entity.
- In my example, I am using OOB ‘Account’ entity which has 10 records.

- When ‘RetrieveEntityChangesRequest’ triggered for the first time, we would get all 10 records in ‘Changes’ object and a ‘Data Token’.

- Copy the ‘Data Token’.
- Now lets delete an Account and add a new Account in CDS.

- Trigger ‘RetrieveEntityChangesRequest’ again by passing the copied ‘Data Token’.
- Passing ‘Data Token’ in ‘RetrieveEntityChangesRequest’, fetches only data for those changes that occurred since that version will be returned.
- This time we would get 2 records in ‘Changes’ object.
- 1 NewOrUpdatedItem
- 1 RemovedOrDeletedItem.

- ‘NewOrUpdatedItem’ is object of type ‘Entity’ with all the properties. ‘RemovedOrDeletedItem’ is object of type ‘EntityReference’ contain only GUID of deleted record.
- Following is the code snippet to track changes and display in console.
// Created or Updated records will be returned as 'Entity' object.
var createdorUpdateRecords = new List<Entity>();
// Deleted records will be returned as 'Entity Reference' object.
var deletedRecords = new List<EntityReference>();
// Retrieve records by using Change Tracking feature.
var request = new RetrieveEntityChangesRequest
{
EntityName = "account",
Columns = new ColumnSet("name"),
PageInfo = new PagingInfo() {
Count = 5000,
PageNumber = 1,
ReturnTotalRecordCount = false
},
// DataVersion is an optional attribute
// If not passed system returns all the records.
// Dont pass this attribute when calling for the first time.
DataVersion = "706904!07/24/2020 08:00:32"
};
while (true)
{
var response = (RetrieveEntityChangesResponse)_serviceProxy.Execute(request);
if (response != null &&
response.EntityChanges != null && response.EntityChanges.Changes != null)
{
foreach (var record in response.EntityChanges.Changes)
{
// Read NewOrUpdatedItem in to 'createdorUpdateRecords' list.
if (record is NewOrUpdatedItem)
{
createdorUpdateRecords.Add((record as NewOrUpdatedItem).NewOrUpdatedEntity);
}
// Read RemovedOrDeletedItem in to 'deletedRecords' list.
if (record is RemovedOrDeletedItem)
{
deletedRecords.Add((record as RemovedOrDeletedItem).RemovedItem);
}
}
}
// Display Created or Updated records
createdorUpdateRecords.ForEach(x => Console.WriteLine("Created or Updated record id:{0}", x.Id));
// Display Deleted records
deletedRecords.ForEach(x => Console.WriteLine("Deleted record id:{0}", x.Id));
// Logic for Pagination
if (!response.EntityChanges.MoreRecords)
{
//Store token for later query
token = response.EntityChanges.DataToken;
break;
}
// Increment the page number to retrieve the next page.
request.PageInfo.PageNumber++;
// Set the paging cookie to the paging cookie returned from current results.
request.PageInfo.PagingCookie = response.EntityChanges.PagingCookie;
- Run the code and you would get response as below

🙂
Delete record synchronously using OData and JScript in CRM 2011
Hi,
Below is the script to delete record synchronously
function deleteRecordSync(recordId, odataSetName) {
// Get Server URL
var serverUrl = Xrm.Page.context.getServerUrl();
//The OData end-point
var ODATA_ENDPOINT = “/XRMServices/2011/OrganizationData.svc”;
var deleteRecordReq = new XMLHttpRequest();
var ODataPath = serverUrl + ODATA_ENDPOINT;
deleteRecordReq.open(‘POST’, ODataPath + “/” + odataSetName + “(guid'” + recordId + “‘)”, false);
deleteRecordReq.setRequestHeader(“Accept”, “application/json”);
deleteRecordReq.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”);
deleteRecordReq.setRequestHeader(“X-HTTP-Method”, “DELETE“);
deleteRecordReq.send(null);
}
How do I call this method :-
- To delete an “Account”
- Pass account GUID and OData Set name (i.e.,AccountSet)
Var accountId=”{Account GUID}”;
deleteRecordSync (accountId , “AccountSet”);
🙂
Deleting a record using OData & JQuery in CRM 2011
Hi,
Below is the script to delete record using OData & JScript
function deleteRecord(id, odataSetName) {
// Get Server URL
var serverUrl = Xrm.Page.context.getServerUrl();
//The OData end-point
var ODATA_ENDPOINT = “/XRMServices/2011/OrganizationData.svc”;
//Asynchronous AJAX function to Delete a CRM record using OData
$.ajax({
type: “POST”,
contentType: “application/json; charset=utf-8”,
datatype: “json”,
url: serverUrl + ODATA_ENDPOINT + “/” + odataSetName + “(guid'” + id + “‘)”,
beforeSend: function (XMLHttpRequest) {
//Specifying this header ensures that the results will be returned as JSON.
XMLHttpRequest.setRequestHeader(“Accept”, “application/json”);
//Specify the HTTP method DELETE to perform a delete operation.
XMLHttpRequest.setRequestHeader(“X-HTTP-Method”, “DELETE”);
},
success: function (data, textStatus, XmlHttpRequest) {
alert(“Record deleted successfully!!!!”);
},
error: function (XmlHttpRequest, textStatus, errorThrown) {
alert(“Error while deletion – “+errorThrown);
}
});
}
How Do I call this method :-
- To delete a “Account” record  set account id & Odata set name and call the above method
var accountId = {}; //Set Account GUID
var odataSeName = “AccountSet”;
deleteRecord(accountId, odataSeName);
Hope it helps 🙂