目的:
在Dynamics CRM 开发中,最常用的就是通过 Create Plugin 和 Update Plugin 来实现各种定制功能,当然也存在使用 Delete Plugin 的情况,本篇就简单讲一下 Delete Plugin 怎么用。
场景:
在CRM开发中,表与表之间通过 lookup 字段来建立,现在假设有以下场景需求:
比如存在一个产品表A以及一个子产品表B,在表B中建立一个lookup A表的字段,而表A中存在一个字段来统计子产品个数(即在表B中有多少条record是指向自己的),那么这个时候,当某个子产品被删除后(record delete),父产品的统计数需要进行对应的更新,此时可以使用 Delete Plugin 来实现这个需求。
实现:
代码比较简单,在执行上下文时判断是否为 Delete Message 即可:
1 public void Execute(IServiceProvider serviceProvider) 2 { 3 ITracingService tracer = (ITracingService)serviceProvider.GetService(typeof(ITracingService)); 4 IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); 5 IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); 6 IOrganizationService service = factory.CreateOrganizationService(context.UserId); 7 8 try 9 { 10 //TODO: Do stuff 11 if (context.MessageName.Equals("Create")) 12 { 13 tracer.Trace("stage " + context.Stage); 14 switch (context.Stage) 15 { 16 case 20: 17 CreatePlugin(tracer, context, service, factory); 18 break; 19 case 40: 20 break; 21 default: 22 break; 23 } 24 } 25 else if (context.MessageName.Equals("Update")) 26 { 27 switch (context.Stage) 28 { 29 case 20: 30 UpdatePlugin(tracer, context, service, factory); 31 break; 32 case 40: 33 break; 34 default: 35 break; 36 } 37 } 38 else if (context.MessageName.Equals("Delete"))//For Delete Plugin 39 { 40 switch (context.Stage) 41 { 42 case 10: 43 DeletePlugin(tracer, context, service, factory); 44 break; 45 } 46 } 47 48 } 49 catch (Exception e) 50 { 51 throw new InvalidPluginExecutionException(e.Message); 52 } 53 54 }
如何在 Detele Request 中拿到当前 Record 的所有信息,代码如下,先获取 EntityReference 对象,再通过这个对象来查找对应 Record:
1 private void DeletePlugin(ITracingService tracer, IPluginExecutionContext context, IOrganizationService service, IOrganizationServiceFactory factory) 2 { 3 tracer.Trace("Start DeletePlugin()"); 4 try 5 { 6 EntityReference entity = ((EntityReference)context.InputParameters["Target"]); 7 Entities.new_entity = service.Retrieve(entity.LogicalName, entity.Id, new ColumnSet(true)).ToEntity<Entities.new_entity>();//获取当前Record的所有信息,之后就可以根据 Lookup 字段来查找父产品
8 } 9 catch (Exception ex) 10 { 11 if (ex.GetType().Name == "InvalidPluginExecutionException") 12 { 13 throw new InvalidPluginExecutionException(ex.Message + Environment.NewLine); 14 } 15 else 16 { 17 string errorText = ex.Message.ToString(); 18 19 while (ex.InnerException != null) 20 { 21 errorText += ex.InnerException.Message; 22 ex = ex.InnerException; 23 } 24 throw new Exception("Error: " + errorText + "\n"); 25 } 26 } 27 tracer.Trace("End DeletePlugin()"); 28 }
Note: CRM 在执行 Delete Request 的时候,与 Create / Update Request 不同,Delete 时 Context 拿到的不是当前 Record 的 Entity 对象,而是 EntityReference 对象,如果强制转换成 Entity 对象会报错,所以记得要把 Execute 方法中这句代码删除:
Entity entity = (Entity)context.InputParameters["Target"];
最后在注册下 Delete Message 即可,使用10 Stage(Pre-validation)或20 Stage(Pre-operation)都可以,一般建议使用10 Stage,因为在20 Stage 时某些 relationship 可能已经删除了,比如 PartyList 类型字段,在20的时候拿不到Value.