You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dynamics CRM同邮箱联系人agr1/agr2同步及新建联系人字段联动咨询

问题解决方案

功能2:新建联系人时agr1、agr2字段联动实现

问题原因

现有插件仅注册了Update消息的触发事件,新建联系人触发的是Create消息,因此逻辑不会执行。

修复方案

  1. 插件构造函数新增Create消息注册,推荐使用PreOperation阶段(20),该阶段修改目标实体属性会直接写入数据库,无需额外调用Update方法,避免递归触发。
  2. 逻辑中区分Create和Update场景:Create场景没有PreImage,直接读取Target实体的字段值判断即可;Update场景保留原有Pre/Post Image的变更判断逻辑。
  3. 原有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字段同步实现

实现方案

  1. 注册独立的插件,绑定PostOperation阶段(40)的Create、Update消息,触发对象为contact实体。
  2. 触发时读取当前联系人的emailaddress1和agr1值,如果邮箱为空直接返回。
  3. 查询所有emailaddress1等于当前邮箱、且ID不等于当前联系人ID的contact记录。
  4. 批量更新查询到的所有联系人的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 05:06:02