Clone Records in Dynamics CRM

By | August 18, 2014

Very often we are troubled with writing huge codes and end up spending our valuable time for cloning/copying Dynamics CRM entity record. Just imagine the time needed if you are asked to create a cloned record with more than 100 attributes. Don’t you think it’s a time-consuming effort and how great would it be if all this could happen just with a two line code?

The below sample code will guide you on how to create a cloned record using Clone() function of Microsoft.Xrm.Client Namespace:

//Add references

using Microsoft.Crm.Sdk;

using Microsoft.Xrm.Sdk;

using OrganizationXrm;

using Microsoft.Crm.Sdk.Messages;

using Microsoft.Crm.Sdk.Samples;

using Microsoft.Xrm.Sdk.Client;

//Used for Clone Function

using Microsoft.Xrm.Client;

 

//Declare Variables

Entity parentaccount= new Entity(“account”);

Guid parentaccountid = Guid.Empty;

Entity childaccount;

Guid childaccountid = Guid.Empty;

 

try

{

//Set attributes of the Parent Account

parentaccount.Attributes["name"] = “Parent Account”;

parentaccount.Attributes["telephone1"] = “Telephone1″;

//create the parent account

parentaccountid = _service.Create(parentaccount);

//Clone the Account Record using Clone function;

//Clone function takes a bool parameter which relates the Related Entities of the parent

//record to the cloned records, if set to true.

//The bool parameter passed to Clone method is set to true by default.

childaccount = parentaccount.Clone(true);

//Remove all the attributes of type primaryid as all the cloned records will have their own primaryid

childaccount.Attributes.Remove(childaccount.LogicalName + “id”);

//Remove the telephone1 attribute from the cloned record to differentiate between the parent and cloned record

childaccount.Attributes.Remove(“telephone1″);

//create the cloned record

childaccountid = _service.Create(childaccount);

}

catch (SaveChangesException ex)

{

throw ex;

}

Notes:

  • It is limited to an On-Premise environment only.
  • Add reference Microsoft.Xrm.Client.
  • Works with commonly used OOB and Custom entities.
  • Removing primaryid attribute from the attribute collection of cloned instance is mandatory.

Cloning a record using JavaScript

Cloning a Dynamics CRM record is not only limited to aCustom Workflow or a Plug-in, the same functionality can be very well achieved in JavaScript with the below workaround.

Below example explains how to Clone Line Items of one Quote onto another Quote.

1. Retrieve Data:

The first step to start off with is to retrieve the records that we need to clone/copy.  In this example since we are Cloning the Line Items, so well retrieve all the Line Items of the Quote from which we need to Clone. All the retrieved Line Items will be stored in a variable called "retrievedProducts". This variable will be later on used to “Create” the Line Items for other Quote.

//Retrieve the Values

XrmServiceToolkit.Rest.RetrieveMultiple

("QuoteDetailSet",

//Here you can have some selected fields or all the fields

options,

function successCallback(results) {

//get the retrieved result in a variable

retrievedProducts = results;

},

function errorCallback(error) {

showError(error, functionName);

},

function onComplete() { },

false);

2. Delete Extra Data

The next step is to remove the extra data. The extra data involves all the ID attributes that can create Duplicity issue. And, the "__metadata" attribute, this attribute contains extra data that is not needed for us to Clone the record and hence well remove it. To remove the unwanted data from the “retrievedProducts” Object, well use thedeletefunctionality.

In this example the "deleteExtraData" function is called at the time of creating the records.

//This function deletes the extra data from the Object

function deleteExtraData(retrievedObject) {

//Remove all the extra fields

delete retrievedObject.__metadata;

delete retrievedObject.QuoteId;

delete retrievedObject.QuoteDetailId;

 

                //Check for all the __metadata fields and remove it

delete retrievedObject.__metadata;

//Loop through Objects in Object

for (var key in retrievedObject) {

if (retrievedObject.hasOwnProperty(key)) {

//Check if the value is null if it is null then do nothing

if (retrievedObject[key] == null) {

 

} else {

//Check the type is the type is object, remove metadata

if (typeof (retrievedObject[key]) == "object") {

//deletes the metadata from the object

delete retrievedObject[key].__metadata;

}

}

}

}

}

3. Create the Record

The final step is the creation of the record. In this step well loop through the retrieved values which in this example is stored in the variable “retrievedProducts ” and create the Line Items one by one for the desired Quote. Since we have removed the Quote Id we need to associate a Quote Id.And, in this step we`ll pass the “retrievedProducts ” Object to the     “deleteExtraData” function. And, the formatted value would be passed for the creation.

for (var j in retrievedProducts) {

//Get the formatted value. formattedQuoteProduct is an Object.

formattedQuoteProduct[j] = deleteExtraData(retrievedProducts[j]);

//Since we removed the Quote Id we need to associate it with another Quote Id as the Quote Line Items needs to have a Quote Id.newQuoteId can be the Quote Id of the Quote on which you need to clone the Line Items

formattedQuoteProduct[j].QuoteId = {

Id: newQuoteId,

LogicalName: “quote”

};

//Create the products

XrmServiceToolkit.Rest.Create(formattedQuoteProduct[j],

“QuoteDetailSet”,

function successCallback() { },

function errorCallback(error) {

showError(error, functionName);

}, false);

 

}

Creating a cloned record using fetch expression:

We have introduced how to clone record using  .Clone()function in On-Premise environment and also by using  JavaScript and now we would like to introduce another method of cloning records which can be used in any environment and allows us to define the attributes to be replicated on the cloned record.

Working:

At first, we will fetch the entity for which we have to clone the records and in the attributes, we will add only those attributes which we need to copy the cloned records.

Here, we have taken the “Account” entity of the CRM to create cloned records:

string sourceqry = @”<fetch version=’1.0′ output-format=’xml-platform’ mapping=’logical’ distinct=’false’>” +

“<entity name=’account’>”+

“<attribute name=’name’/>”+

“<attribute name=’primarycontactid’/>”+

“<attribute name=’telephone1’/>”+

“<attribute name=’accountid’/>”+

“<order attribute=’name’ descending=’false’/>”+

“<filter type=’and’>”+

“<condition attribute=’name’ operator=’eq’ value=’XXXXXX’/>” +

“</filter>”+

“</entity>”+

“</fetch>”;

 

//Declare an entity collection to hold the entities retreived by the query

EntityCollection AccountsCollection = service.RetrieveMultiple(newFetchExpression(sourceqry));

 

if (AccountsCollection.Entities.Count > 0)

{

for (int count = 0; count < AccountsCollection.Entities.Count; count++)

{

Entity account = AccountsCollection.Entities[count];

 

//Set the EntityState to null, so that a new cloned record can be created

account.EntityState = null;

 

//remove the PrimaryId of the record

account.Attributes.Remove(account.LogicalName + “id”);

 

//Set any field of the cloned record to differentiate between the parent and the cloned record

account.Attributes["name"] = “Cloned record created at: ” + System.DateTime.Now;

 

//set a unique id to the cloned record

account.Id = Guid.NewGuid();

 

//Create the new cloned record

service.Create(account);

}

}

}

catch (SaveChangesException ex)

{

throw ex;

}

catch (FaultException<OrganizationServiceFault> ex)

{

throw ex;

}

catch (Exception ex)

{

throw ex;

}

In the above code snippet we have cloned the “Account” entity records where name of the “Account” is “XXXXX” and we have just added only few attributes in the fetch expression which we need to get copied to the new cloned records.

Note:

  • Set the “EntityState” to”null”.
  • Remove the “PrimaryId” of the record.
  • Any (OOB + Custom) entity can be cloned.

Leave a Reply