65.9K
CodeProject 正在变化。 阅读更多。
Home

复制或克隆 Dynamics 365 CRM 中的父记录以及所有关联的子记录,从一个实体到另一个实体。

2024 年 5 月 5 日

CPOL

2分钟阅读

viewsIcon

4939

在 Dynamics CRM 中创建一个插件,该插件复制现有记录及其子记录,从一个实体到另一个实体,无需字段映射。

引言

我需要克隆/复制动态 CRM 实体的记录及其所有相关的子记录。 我可以通过添加关系并将源实体字段与目标实体字段映射来轻松克隆主实体。 但是,挑战在于复制/克隆其子记录并将其链接起来。

背景

您需要了解 Dynamics CRM 插件或自定义工作流开发(代码活动)。
要在 Dynamics 365 CRM 中从一个实体复制或克隆子记录到另一个实体,通常需要使用自定义代码来自动化该过程。 该过程包括查询与一个实体中的特定记录相关的子记录,在目标实体中创建新记录,并在它们之间建立关系。

问题在于单独映射所有字段,这非常繁琐。 假设关联实体记录中有 100 个字段,并且您想克隆相关实体中的所有字段。 然后,您最终只会编写 100 行代码。 此外,每当您添加新字段时,都必须更新插件代码。

我尝试消除为每个字段映射编写代码,并在 MeghShyam Gaur 的帖子 此处 找到了一种巧妙的解决方案。 主要技巧是删除检索到的关联记录的主键,并将主键值设置为 Guid.NewGuid(),最后删除检索到的关联记录的父记录 ID。

使用代码

  1. 克隆主实体
            public static Entity CloneEntitySandbox(Entity entityToClone)
            {
                var newEntity = new Entity(entityToClone.LogicalName);
                
                //To exclude the following fields from cloning
                var systemAttributes = new List<string>();
                systemAttributes.Add("createdon");
                systemAttributes.Add("createdby");
                systemAttributes.Add("modifiedon");
                systemAttributes.Add("modifiedby");
                systemAttributes.Add("owninguser");
                systemAttributes.Add("owningbusinessunit");
        
        
                foreach (var attribute in entityToClone.Attributes
                    .Where(x => x.Key != entityToClone.LogicalName + "id")
                    .Where(x => !systemAttributes.Contains(x.Key))) 
                {
        
                    switch (attribute.Value.GetType().Name)
                    {
                        case "Money":
                            var m = attribute.Value as Money;
                            newEntity[attribute.Key] = new Money(m.Value);
                            break;
                        case "EntityReference":
                            var er = attribute.Value as EntityReference;
                            newEntity[attribute.Key] = new EntityReference(er.LogicalName, er.Id);
                            break;
                        case "OptionSetValue":
                            var os = attribute.Value as OptionSetValue;
                            newEntity[attribute.Key] = new OptionSetValue(os.Value);
                            break;
                        default:
                            newEntity[attribute.Key] = attribute.Value;
                            break;
                    }
        
                }
        
                return newEntity;
            }
            
            
  2. 识别源子实体和目标子实体

    确定源 entityId(子记录存在的位置)和目标 entityId(要复制子记录的位置)。

    //In the below example I am going to clone all contacts from one account to another account
    CloneEntityassociatedRecordsToAnother(orgService, sourceEntityId,  targetEntityId,"parentcustomerid","contact", "contactid");
  3. 查询子记录

    以下步骤是从一个实体到另一个实体创建子记录克隆。 假设您正在使用插件或自定义工作流。

    public void CloneEntityassociatedRecordsToAnother(IOrganizationService organizationService,Guid sourceEntityId, Guid targetEntityId, string strForignKeyAttributeName, string strDetailEentityLogicalName, string strDetailEntityPrimaryKeyName)
    {
        try
        {
            QueryExpression query = new QueryExpression{ EntityName = strDetailEentityLogicalName, ColumnSet = new ColumnSet(true),
                Criteria = {FilterOperator = LogicalOperator.And, Conditions = {
                        new ConditionExpression {
                                AttributeName = strForignKeyAttributeName,
                                Operator = ConditionOperator.Equal,
                                Values = { sourceEntityId.ToString()}}
                    }}
            };
    
            //Instead of iterating through all the child records and creating one by one we can also use ExecuteMultiple method
            foreach (Entity retrieve in organizationService.RetrieveMultiple(query).Entities)
            {
                //Remove the primary key of the retrieved associated record
                retrieve.Attributes.Remove(strDetailEntityPrimaryKeyName);
    
                //Set the primary key value to Guid.NewGuid()
                retrieve.Id = Guid.NewGuid();
                
                //Remove the parent record id of the retrieved associated record
                retrieve.Attributes.Remove(strForignKeyAttributeName);
    
                EntityReference newContractId = SetRefrence(strDetailEentityLogicalName, targetEntityId);
                retrieve.Attributes.Add(strForignKeyAttributeName, newContractId);
                organizationService.Create(retrieve);
            }
        }
        catch (Exception ex)
        {
            throw new InvalidPluginExecutionException("Clone Entityassociated Records To Another Plugin: " + ex.Message);
        }
    }
  4. 在新创建的记录和目标实体之间建立关系。

        public static EntityReference SetRefrence(string Ent, Guid entRef)
        {
            EntityReference r_EntRef = null;
            if (entRef != null) r_EntRef = new EntityReference(Ent, entRef);
        
            return r_EntRef;
        }

关注点

  • 错误处理:实施适当的错误处理机制,以管理复制过程中出现的任何问题。
  • 测试:在将解决方案部署到生产环境之前,请在开发环境中对其进行全面测试。

参考文献

在此处保持您所做的任何更改或改进的实时更新。

© . All rights reserved.