Sunday, 31 March 2013

Clone CRM Record CRM 2011


Many times while working on CRM 2011, we come across a situation to clone the quote or invoice records. Immediately we will start writing the code for getting the record and creating the same record again and continue the same for child records i.e. quote products or invoice lines etc...

Even I have came across the same situation then my team lead and me wrote a generic method for cloning CRM records.

Here is that method...

        #region CloneRecord
                /// <summary>
                /// Method to Clone CRM Record.
                /// </summary>
                /// <param name="strEntityName">Parent entity name ex: invoice</param>
                /// <param name="strParentEntityPKAttrName">Parent primary attribute name ex:invoiceid</param>
                /// <param name="guidParent">Guid of the parent record</param>
                /// <param name="strAttributesToFetch">Selected attributes to copy from one record to another. If you wanna copy all records,
                /// just send the parameter as null then the considers all attributes.</param>
                /// <param name="strArrRemoveParentAttributes">Attributes to remove from parent entity.</param>
                /// <param name="strChildEntity">Child entity name ex: invoicedetail</param>
                /// <param name="strChildEntityFKAttrName">Child primary attriubute name ex: invoicedetailid</param>
                /// <param name="strArrRemoveChildCols">Attributes to remove from child entity</param>
               /// <returns>Guid of the parent record</returns>
                public Guid CloneCRMRecord(string strEntityName, string strParentEntityPKAttrName, Guid guidParent, string[] strAttributesToFetch, string[] strArrRemoveParentAttributes, string strChildEntity, string strChildEntityFKAttrName, string[] strArrRemoveChildCols)
                {
                    Microsoft.Xrm.Sdk.Entity parentEntity = new Microsoft.Xrm.Sdk.Entity(strEntityName);
                    if (strAttributesToFetch == null)
                    {
                        parentEntity = _crmService.Retrieve(parentEntity.LogicalName, guidParent, new ColumnSet(true));
                    }
                    else
                    {
                        parentEntity = _crmService.Retrieve(parentEntity.LogicalName, guidParent, new ColumnSet(strAttributesToFetch));
                    }
                    if (strArrRemoveParentAttributes == null) strArrRemoveParentAttributes = new string[] { "" };
                    RemoveEntityAttributes(ref parentEntity, strArrRemoveParentAttributes);
                    /*
                        Below line is must otherwise, "Create" will result in:
                        FaultException'1 was unhandled.
                        Cannot insert duplicate key.
                    */
                    parentEntity.Id = Guid.NewGuid();
                    Guid newEntityRecordId = _crmService.Create(parentEntity);
                    //
                    if (string.IsNullOrEmpty(strChildEntity) == false)
                    {
                        #region Retrieve all the Child Entity Record details from the original Parent Entity Record.
                                ConditionExpression expression = new ConditionExpression();
                                expression.AttributeName = strChildEntityFKAttrName;
                                expression.Operator = ConditionOperator.Equal;
                                expression.Values.Add(guidParent);
                                FilterExpression expression2 = new FilterExpression();
                                expression2.FilterOperator = LogicalOperator.And;
                                expression2.Conditions.Add(expression);
                                QueryExpression query = new QueryExpression();
                                query.EntityName = strChildEntity;
                                query.ColumnSet = new ColumnSet(true);
                                query.Criteria = expression2;

                        #endregion
                        EntityCollection allChildEntityRecords = _crmService.RetrieveMultiple
(query);
                        if (allChildEntityRecords != null)
                        {
                            //One by one create Child Entity records in the Parent Entity.sales order detail record and set its FK Id to the Cloned Parent Entity Id
                            //and PK Id to new GUID.
                            #region Create Child Entity Records under the Parent Entity.
                                    Microsoft.Xrm.Sdk.Entity clonedChildEntity = null;
                                    if (strArrRemoveChildCols == null) strArrRemoveChildCols = new string[] { "" };
                                    Guid newChildEntityRecordId = Guid.Empty;
                                    foreach (Microsoft.Xrm.Sdk.Entity childEntity in allChildEntityRecords.Entities)
                                    {
                                        clonedChildEntity = new Microsoft.Xrm.Sdk.Entity(strChildEntity);
                                        clonedChildEntity = _crmService.Retrieve(clonedChildEntity.LogicalName, childEntity.Id, new ColumnSet(true));
                                        EntityReference refParent = new EntityReference(parentEntity.LogicalName, parentEntity.Id);
                                        clonedChildEntity.Attributes[strChildEntityFKAttrName] = refParent;
                                        RemoveEntityAttributes(ref clonedChildEntity, strArrRemoveChildCols);
                                        /*
                                            Below line is must otherwise, "Create" will
result in: FaultException'1 was unhandled. Cannot insert duplicate key.
                                        */
                                        clonedChildEntity.Id = Guid.NewGuid();
                                        newChildEntityRecordId = _crmService.Create(clonedChildEntity);
                                    }
                            #endregion
                        }
                    }
                    return parentEntity.Id;
                }
          
                 //Method to remove attributes from entity.
                private void RemoveEntityAttributes(ref Microsoft.Xrm.Sdk.Entity inputEntity, string[] strArrRemoveCols)
                {
                    for (int intLoop = 0; intLoop < strArrRemoveCols.Length; intLoop++)
                    {
                        inputEntity.Attributes.Remove(strArrRemoveCols[intLoop]);
                    }
                }
        #endregion

 Happy Programming.... :)

 

3 comments:

  1. Your code wont work as it throw the following exception "Entity Id must be the same as the value set in property bag"

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. Adding this line just before creating the entity will help
    RemoveEntityAttributes(ref parentEntity, new string[] {strParentEntityPKAttrName});

    ReplyDelete