经常有这样的需求,一个单据上有太多要填写的内容,有时还关联多个子单据,客户不想一个一个地填写,他们想从已有的单据上复制数据,克隆成一条新的记录。本文将介绍如何克隆一条记录,包括它的子单据以生成一条新的记录。

主要用到Microsoft.Xrm.Client.EntityExtensions.Clone方法来克隆数据,以及用OrganizationServiceContext来动态复制子单据的数据。

首先在界面上新加一个Clone的按钮,加一个new_clone的字段;点击按钮时,把new_clone字段设为clone以触发插件,插件里完成数据的复制工作,并再次把new_clone字段设成新数据的id,new_clone的onchange事件会调用Xrm.Utility.openEntityForm("new_marketing_plan", cloneValue);来打开新的数据。

下面看下实现方法:

1. 界面上js:

  function openNewEntity() {
      var clone = Xrm.Page.getAttribute("new_clone");
      var cloneValue = clone.getValue();
      if (cloneValue != "clone" && cloneValue != "") {
          clone.setSubmitMode("always");
          clone.setValue("");
          Xrm.Page.data.entity.save();
          Xrm.Utility.openEntityForm("new_marketing_plan", cloneValue);
      }
  }   //clone button click event   function clone() {
      var clone = Xrm.Page.getAttribute("new_clone");
      clone.setSubmitMode("always");
      clone.setValue("clone");
      Xrm.Page.data.entity.save();
  }

2. 主单据复制:

new_marketing_plan newMP = (new_marketing_plan)Microsoft.Xrm.Client.EntityExtensions.Clone(curEnt, true);
new_marketing_plan mp = new new_marketing_plan() { Id = newMP.Id };
Guid newMPid = Guid.NewGuid();
newMP.Attributes.Remove("new_marketing_planid");
newMP.Attributes.Remove("new_name");
newMP.new_approval_status = new OptionSetValue(1);
newMP.new_clone = "";
newMP.EntityState = null;
newMP.Id = newMPid;
adminService.Create(newMP);

3. 子表复制:

我这里有9个子表,所以抽出了一个方法以方便使用, 以后要是子单据有变化,只用改下这里的entNames就行了。

  //clone field change event
 string entNames = "new_print_plan,new_radio_plan,new_bill_board,new_tv_plan,new_btl_posm,new_btl_poe_fixed,new_promotion_girls,new_promotion_events,new_digital_plan";
 foreach (string entName in entNames.Split(','))
 {
   CloneRelatedEntities(adminService, newMPid, entName, "new_marketing_planid", mp);
 }  curEnt["new_clone"] = newMPid.ToString();
 adminService.Update(curEnt);
  private void CloneRelatedEntities(IOrganizationService adminService, Guid newEntityId, string subEntityName, string filterName, Entity parentEntity)
{  
        using (OrganizationServiceContext svcContext = new OrganizationServiceContext(adminService))
        {
            var ents = svcContext.CreateQuery(subEntityName).Where(e => e[filterName] == parentEntity[filterName]).ToList();
            foreach (var ent in ents)
            {
                 var newEnt = Microsoft.Xrm.Client.EntityExtensions.Clone(ent);
                 newEnt.Attributes[filterName] = new EntityReference(subEntityName, newEntityId);
                 newEnt.Id = Guid.NewGuid();
                 newEnt.EntityState = null;
                 adminService.Create(newEnt);
             }
         }
 }

4. 注意事项

  • 当我完成Unit Test,注册完插件后,报了下面的错:

Could not load file or assembly 'Microsoft.Xrm.Client, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified

原来这个Client dll在服务器上是没有的,需要我们手动copy上去。从我们本机的“SDK\Bin”里copy到服务器上的“program files\Microsoft Dynamics CRM\CRMWeb\bin”下即可。

  • 再点击Clone按钮,又报了一个错:

This workflow job was canceled because the workflow that started it included an infinite loop. Correct the workflow logic and try again. For information about workflow logic, see Help

原来出现死循环了,解决方法很简单,在插件的开始处加上下面代码就行了:

if (context.Depth > 1)
            {

return;

}

Dynamic CRM 2013学习笔记 系列汇总

Dynamic CRM 2013学习笔记(十四)复制/克隆记录的更多相关文章

  1. Dynamic CRM 2013学习笔记(四十六)简单审批流的实现

    前面介绍过自定义审批流: Dynamic CRM 2013学习笔记(十九)自定义审批流1 - 效果演示 Dynamic CRM 2013学习笔记(二十一)自定义审批流2 - 配置按钮 Dynamic ...

  2. Dynamic CRM 2013学习笔记(四十二)流程5 - 实时/同步工作流(Workflow)用法图解

    实时工作流跟插件一样,也是用事件执行管道来执行,能在pre,post或核心操作中执行.跟插件一样,不能在创建之前和删除之后执行.如果执行过程中有异常发生,会取消并回滚整个操作.实时工作流里所有的活动和 ...

  3. Dynamic CRM 2013学习笔记(四十)流程3 - 对话(Dialog)用法图解

    我们将用对话来实现一个简单的满意度调查,下一个问题依赖于上一个问题.对话是同步的,不同于工作流既可以是同步也可以是异步的:对话可以跟用户互动:对话只能手动开始:对话只支持 .Net Framework ...

  4. Dynamic CRM 2013学习笔记(四十四)CRM技术支持

    有时我们经常遇到一些CRM的问题,一时又无法解决,这时我们可能要找下外援,下面列出一些基本的技术支持.   1. CRM 论坛 https://community.dynamics.com/crm/f ...

  5. Dynamic CRM 2013学习笔记(四十五)修改实体及字段的前缀(不用new_开头)

    最近做一个升级的CRM项目,为了区分哪些是新增的,所以决定用一个新的前缀来定义实体及新加的字段.之前用的是new_开头,现在改成tm_开头.   原来只要是新建实体或字段都是new_开头:   1. ...

  6. Dynamic CRM 2013学习笔记(四)单据编号及插件批量注册工具

    基本上每个实体form上都会有单据编号,而且不同的实体编号要求还不太一样,这时就需要一个通用的单据编号插件,可配置以应对不同的需求. 下面简单介绍下实现步骤: 1. 创建二个实体,以保存各实体所要求的 ...

  7. Dynamic CRM 2013学习笔记(四十一)流程4 - 异步工作流(Workflow)用法图解

    在CRM 2013 里,工作流被分成二类:异步工作流和实时工作流.异步工作流依赖一个windows 服务: Microsoft Dynamics CRM Asynchronous Processing ...

  8. Dynamic CRM 2013学习笔记(四十三)流程6 - 自定义流程活动

    当我们在流程里添加步骤时,有一些默认的步骤,像创建.更新.发邮件等,但如果你想加一个里面没有的步骤,比如发SMS消息,或者调用一个外部的web service,怎么办?这时就只能自定义一个流程活动了. ...

  9. Dynamic CRM 2013学习笔记 系列汇总

    这里列出所有 Dynamic CRM 2013学习笔记 系列文章,方便大家查阅.有任何建议.意见.需要,欢迎大家提交评论一起讨论. 本文原文地址: Dynamic CRM 2013学习笔记 系列汇总 ...

随机推荐

  1. mgo中DBRef-数据查询测试

    下午对数据查询进行了代码测试: package main import ( "crypto/rand" "encoding/hex" "fmt&quo ...

  2. 第一零三天上课 PHP TP框架下控制器的方法分离

    (1)配置信息 修改配置文件->Config.php (配置后,原先的控制方法无效) 'ACTION_BIND_CLASS' => TRUE, // 控制器方法分离 (2)在Control ...

  3. hive中的桶

    hive中有桶的概念,对于每一个表或者分区,可以进一步组织成桶,说白点,就是更细粒度的数据范围.hive采用列值哈希,然后除以桶的个数以求余的方式决定该条记录存放在哪个桶当中.使用桶的好处:1.获得更 ...

  4. exports 和 module.exports 的区别

    https://cnodejs.org/topic/5231a630101e574521e45ef8 //一句话总结:exports是对module.exports的引用,require()返回的是 ...

  5. CSS3常用选择器(一)

    在 CSS 中,选择器是一种模式,用于选择需要添加样式的元素.比如最常用到的#id,.class,标签选择器. 随着CSS3到来,增加了很多新型选择器,这里就常用的做一个总结. 1.属性选择器. 在c ...

  6. 未能加载文件或程序集Microsoft.ReportViewer.WebForms, Version=10.0.0.0

    解决方案如下ASP.NET项目使用VS2010开发,部署到windows 2008环境中,出现未能加载文件或程序集“Microsoft.ReportViewer.WebForms, Version=1 ...

  7. lstm

    http://colah.github.io/posts/2015-08-Understanding-LSTMs/ 这里介绍lstm写的很不错,尤其是按照不同的part进行解析,感觉很好,很清晰.

  8. DevOps的修炼之路!

    作为一名产品经理,首先要知道产品对于所属公司来说意味着什么,要探寻这个问题,我们又得知道和公司息息相关的是什么,在我的理解来看,与公司状况相关的因素有以下这些: 市场份额 平均订单金额 盈利能力 资产 ...

  9. 使用commons-logging和log4j记录日志

    一,为什么要使用commons-logging+log4j? commons-logging和log4j都是Apache下的开源项目.commons-logging的目的是为“所有的Java日志实现” ...

  10. Android之ImageView 旋转

    方案一: (1)获取ImageView对应的图片,并将其转成Bitmap; (2)创建Matrix对象; (3)调用matrix.setRotate(     );设置旋转度数 (4)重新创建bitm ...