Dynamics CRM同邮箱联系人agr1/agr2同步及新建联系人字段联动咨询
问题解决方案
功能2:新建联系人时agr1、agr2字段联动实现
问题原因
现有插件仅注册了Update消息的触发事件,新建联系人触发的是Create消息,因此逻辑不会执行。
修复方案
- 插件构造函数新增
Create消息注册,推荐使用PreOperation阶段(20),该阶段修改目标实体属性会直接写入数据库,无需额外调用Update方法,避免递归触发。 - 逻辑中区分
Create和Update场景:Create场景没有PreImage,直接读取Target实体的字段值判断即可;Update场景保留原有Pre/Post Image的变更判断逻辑。 - 原有Post阶段调用
service.Update的逻辑可以移除,Pre阶段直接修改Target属性即可生效,降低性能损耗。
修改后代码示例
namespace IfZgodaChangeMassmailingChange { using System; using System.Linq; using System.ServiceModel; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Client; using Microsoft.Xrm.Sdk.Query; public class IfZgodaChangeMassmailingChange : IfZgodaChangeSetZgoda2.Plugin { public IfZgodaChangeMassmailingChange() : base(typeof(IfZgodaChangeMassmailingChange)) { // 原有Update消息注册,调整为PreOperation阶段(20),如果保留Post阶段可自行改回40 base.RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(20, "Update", "contact", new Action<LocalPluginContext>(Execute))); // 新增Create消息注册,PreOperation阶段 base.RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(20, "Create", "contact", new Action<LocalPluginContext>(Execute))); } protected void Execute(LocalPluginContext localContext) { if (localContext == null) throw new ArgumentNullException("localContext"); IPluginExecutionContext context = localContext.PluginExecutionContext; IOrganizationService service = localContext.OrganizationService; ITracingService tracingService = localContext.TracingService; if (context.IsExecutingOffline || context.IsOfflinePlayback) return; if (context.Depth > 1) return; if (!context.InputParameters.Contains("Target") || context.InputParameters["Target"] is not Entity entity) return; if (entity.LogicalName != "contact") return; try { bool agr1Current, agr2Current; bool isCreate = context.MessageName == "Create"; bool isUpdate = context.MessageName == "Update"; if (isCreate) { // 新建场景直接取Target的字段值,默认值为false agr1Current = entity.GetAttributeValue<bool>("agr1"); agr2Current = entity.GetAttributeValue<bool>("agr2"); if (agr1Current == false && !entity.Contains("agr2")) { entity["agr2"] = false; } else if (agr2Current == true && !entity.Contains("agr1")) { entity["agr1"] = true; } } else if (isUpdate) { Entity _preEntity = context.PreEntityImages.Contains("PreImage") ? context.PreEntityImages["PreImage"] : null; Entity _postEntity = context.PostEntityImages.Contains("PostImage") ? context.PostEntityImages["PostImage"] : null; if (_preEntity == null || _postEntity == null) return; bool agr1pre = _preEntity.GetAttributeValue<bool>("agr1"); bool agr1post = _postEntity.GetAttributeValue<bool>("agr1"); bool agr2pre = _preEntity.GetAttributeValue<bool>("agr2"); bool agr2post = _postEntity.GetAttributeValue<bool>("agr2"); if (agr1pre == true && agr1post == false) { entity["agr2"] = false; } else if (agr2pre == false && agr2post == true) { entity["agr1"] = true; } } } catch (FaultException<OrganizationServiceFault> e) { tracingService.Trace("Exception: {0}", e.ToString()); throw; } catch (Exception e) { tracingService.Trace("Exception: {0}", e.ToString()); throw; } } [RequiredArgument] [Input("contact")] [ReferenceTarget("contact")] public InArgument<EntityReference> contact { get; set; } } }
额外配置
Update消息需要保留PreImage和PostImage的配置,包含agr1、agr2两个字段即可。
功能1:同邮箱联系人agr1字段同步实现
实现方案
- 注册独立的插件,绑定
PostOperation阶段(40)的Create、Update消息,触发对象为contact实体。 - 触发时读取当前联系人的
emailaddress1和agr1值,如果邮箱为空直接返回。 - 查询所有
emailaddress1等于当前邮箱、且ID不等于当前联系人ID的contact记录。 - 批量更新查询到的所有联系人的
agr1字段为当前值,注意保留Depth>1的判断避免循环触发。
如果仅需要针对john1@example.com这个特定邮箱生效,新增邮箱判断逻辑即可。
代码示例
public class SyncAgr1ByEmail : Plugin { public SyncAgr1ByEmail() : base(typeof(SyncAgr1ByEmail)) { RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(40, "Create", "contact", ExecuteSync)); RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(40, "Update", "contact", ExecuteSync)); } protected void ExecuteSync(LocalPluginContext localContext) { var context = localContext.PluginExecutionContext; var service = localContext.OrganizationService; var tracing = localContext.TracingService; if (context.Depth > 1) return; if (!context.InputParameters.TryGetValue("Target", out Entity target) || target.LogicalName != "contact") return; Entity postEntity = context.PostEntityImages.Contains("PostImage") ? context.PostEntityImages["PostImage"] : target; string email = postEntity.GetAttributeValue<string>("emailaddress1"); if (string.IsNullOrWhiteSpace(email)) return; // 如果只针对特定邮箱生效,放开下面的注释 // if (!email.Equals("john1@example.com", StringComparison.OrdinalIgnoreCase)) return; bool agr1Value = postEntity.GetAttributeValue<bool>("agr1"); Guid currentId = postEntity.Id; // 查询同邮箱的其他联系人 QueryExpression query = new QueryExpression("contact") { ColumnSet = new ColumnSet("contactid"), Criteria = new FilterExpression() { Conditions = { new ConditionExpression("emailaddress1", ConditionOperator.Equal, email), new ConditionExpression("contactid", ConditionOperator.NotEqual, currentId) } } }; var contacts = service.RetrieveMultiple(query).Entities; if (!contacts.Any()) return; // 批量更新 foreach (var contact in contacts) { Entity updateEntity = new Entity("contact", contact.Id); updateEntity["agr1"] = agr1Value; service.Update(updateEntity); } } }
额外配置
需要为该插件配置PostImage,包含agr1、emailaddress1字段。
内容的提问来源于stack exchange,提问作者encoder93x
相关产品推荐
相关产品推荐

