我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面的微软最有价值专家(Microsoft MVP),欢迎关注我的微信公众号 MSFTDynamics365erLuoYong ,回复355或者20190827可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!
前面的文章 Dynamics 365 CE在Pre Delete插件中应用Image 讲了Delete消息PreOperation阶段Image的应用,今天我们来看下Update 消息PostOperation阶段Image的尝试。
我使用如下代码简单注册一个插件:
using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Query; using System; using System.ServiceModel; using System.Text; namespace CRM.Plugins { public class PostWorkOrderUpdate : IPlugin { public void Execute(IServiceProvider serviceProvider) { ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService)); IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity) { Entity currentEntity = (Entity)context.InputParameters["Target"]; IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); Entity preImgEntity; Entity postImgEntity; Entity retrieveEntity; StringBuilder sb = new StringBuilder(); try { if (context.PreEntityImages.Contains("PreImg")) { preImgEntity = context.PreEntityImages["PreImg"]; } else { throw new InvalidPluginExecutionException("Pre Update image - PreImg does not exist!"); } if (context.PostEntityImages.Contains("PostImg")) { postImgEntity = context.PostEntityImages["PostImg"]; } else { throw new InvalidPluginExecutionException("Post Update image - PostImg does not exist!"); } retrieveEntity = service.Retrieve(currentEntity.LogicalName, currentEntity.Id, new ColumnSet("ly_singletext2", "ly_singletext3")); if (retrieveEntity.Contains("ly_singletext2")) { sb.Append("retrieveEntity contains attribute ly_singletext2 = "); sb.Append(retrieveEntity.GetAttributeValue<string>("ly_singletext2")); sb.Append("; "); } else { sb.Append("retrieveEntity does not contain attribute ly_singletext2"); sb.Append("; "); } if (currentEntity.Contains("ly_singletext2")) { sb.Append("currentEntity contains attribute ly_singletext2 = "); sb.Append(currentEntity.GetAttributeValue<string>("ly_singletext2")); sb.Append("; "); } else { sb.Append("currentEntity does not contain attribute ly_singletext2"); sb.Append("; "); } if (preImgEntity.Contains("ly_singletext2")) { sb.Append("preImgEntity contains attribute ly_singletext2 = "); sb.Append(preImgEntity.GetAttributeValue<string>("ly_singletext2")); sb.Append("; "); } else { sb.Append("preImgEntity does not contain attribute ly_singletext2"); sb.Append("; "); } if (postImgEntity.Contains("ly_singletext2")) { sb.Append("postImgEntity contains attribute ly_singletext2 = "); sb.Append(postImgEntity.GetAttributeValue<string>("ly_singletext2")); sb.Append("; "); } else { sb.Append("postImgEntity does not contain attribute ly_singletext2"); sb.Append("; "); } if (retrieveEntity.Contains("ly_singletext3")) { sb.Append("retrieveEntity contains attribute ly_singletext3 = "); sb.Append(retrieveEntity.GetAttributeValue<string>("ly_singletext3")); sb.Append("; "); } else { sb.Append("retrieveEntity does not contain attribute ly_singletext3"); sb.Append("; "); } if (currentEntity.Contains("ly_singletext3")) { sb.Append("currentEntity contains attribute ly_singletext3 = "); sb.Append(currentEntity.GetAttributeValue<string>("ly_singletext3")); sb.Append("; "); } else { sb.Append("currentEntity does not contain attribute ly_singletext3"); sb.Append("; "); } if (preImgEntity.Contains("ly_singletext3")) { sb.Append("preImgEntity contains attribute ly_singletext3 = "); sb.Append(preImgEntity.GetAttributeValue<string>("ly_singletext3")); sb.Append("; "); } else { sb.Append("preImgEntity does not contain attribute ly_singletext3"); sb.Append("; "); } if (postImgEntity.Contains("ly_singletext3")) { sb.Append("postImgEntity contains attribute ly_singletext3 = "); sb.Append(postImgEntity.GetAttributeValue<string>("ly_singletext3")); sb.Append("; "); } else { sb.Append("postImgEntity does not contain attribute ly_singletext3"); sb.Append("; "); } throw new InvalidPluginExecutionException(sb.ToString()); } catch (FaultException<OrganizationServiceFault> ex) { throw new InvalidPluginExecutionException("An error occurred in PostWorkOrderUpdate.", ex); } catch (Exception ex) { tracingService.Trace("PostWorkOrderUpdate unexpected exception: {0}", ex.Message); throw; } } } } }
插件注册信息如下:
我还为此Step注册了两个Image,一个为Pre阶段的Image,一个为Post阶段的Image,如下:
然后我进行了一系列测试:
如果两个字段都变化,获取到的消息如下:
retrieveEntity contains attribute ly_singletext2 = 5-New; currentEntity contains attribute ly_singletext2 = 5-New; preImgEntity contains attribute ly_singletext2 = 5; postImgEntity contains attribute ly_singletext2 = 5-New; retrieveEntity contains attribute ly_singletext3 = 总体满意度-New; currentEntity contains attribute ly_singletext3 = 总体满意度-New; preImgEntity contains attribute ly_singletext3 = 总体满意度; postImgEntity contains attribute ly_singletext3 = 总体满意度-New;
如果只更改一个字段ly_singletext2的值,另外一个字段ly_singletext3不变,保存后获取的结果是:
retrieveEntity contains attribute ly_singletext2 = 5-New; currentEntity contains attribute ly_singletext2 = 5-New; preImgEntity contains attribute ly_singletext2 = 5; postImgEntity contains attribute ly_singletext2 = 5-New; retrieveEntity contains attribute ly_singletext3 = 总体满意度; currentEntity does not contain attribute ly_singletext3; preImgEntity contains attribute ly_singletext3 = 总体满意度; postImgEntity contains attribute ly_singletext3 = 总体满意度;
如果只更改一个字段ly_singletext2的值,这里将其值清空,另外一个字段ly_singletext3不变,保存后获取的结果是:
retrieveEntity does not contain attribute ly_singletext2; currentEntity contains attribute ly_singletext2 = ; preImgEntity contains attribute ly_singletext2 = 5; postImgEntity does not contain attribute ly_singletext2; retrieveEntity contains attribute ly_singletext3 = 总体满意度; currentEntity does not contain attribute ly_singletext3; preImgEntity contains attribute ly_singletext3 = 总体满意度; postImgEntity contains attribute ly_singletext3 = 总体满意度;
如果只更改一个字段ly_singletext2的值,本来该字段的值为空,这里设置其值为New,另外一个字段ly_singletext3的值一直为空保持不变,保存后获取的结果是:
retrieveEntity contains attribute ly_singletext2 = New; currentEntity contains attribute ly_singletext2 = New; preImgEntity does not contain attribute ly_singletext2; postImgEntity contains attribute ly_singletext2 = New; retrieveEntity does not contain attribute ly_singletext3; currentEntity does not contain attribute ly_singletext3; preImgEntity does not contain attribute ly_singletext3; postImgEntity does not contain attribute ly_singletext3;
总结下:
- Target参数转换后的实体会包括所有要设置新值的字段(属性),如果要设置的新值为空值,也会包括该字段(属性),只是该字段(属性)的值为空。
- Target参数转换后的实体不会包括不更改的字段(属性)。
- Pre Update Image包括了字段更新之前的值,如果之前该字段的值为空值,则Pre Update Image不会包括这个字段(属性);
- Post Update Image包括了字段(属性)要更新的值,如果字段(属性)是更新为空值则Post Update Image不包括该字段,如果字段(属性)不更新的话,Post Update Image包括的就是这个字段(属性)的原值;
- 在Post Update阶段查询当前实体的字段(属性)值,查询到的是要变更的新值,如果字段(属性)要要更新为空值,查询结果的字段(属性)集中不会包括该字段(属性),所以不用再查询,直接从Target参数转换后的实体的字段(属性)集合中获取。
- 如果要看字段(属性)值在Update消息中是否变化的话,检查Target参数转换后的实体是否包括该字段(属性)即可,新值在Target参数转换后的实体的字段(属性)集合中,旧值可以用Pre Update Image来获取。
- 获取Image之前先检查Image是否存在,分别用类似context.PreEntityImages.Contains("PreImg") 或者 context.PostEntityImages.Contains("PostImg")。
- 获取字段(属性)值之前先检查字段(属性)的确存在,用类似 currentEntity.Contains("ly_singletext2") 的语法。