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

Microsoft Dynamics CRM 2016插件开发:更新账户地址同步联系人地址

Sync Updated Account Address to Linked Contacts in Dynamics CRM 2016

Hey there, I’ve worked with Dynamics CRM 2016 on-prem quite a bit, so I know exactly how tricky this address sync can be since addresses live in their own customeraddress entities. Let’s walk through a working code snippet that’ll do exactly what you need—syncing the updated account address to all linked contacts.

Key Background

In CRM, account and contact addresses are stored as separate customeraddress records, linked via lookup fields (like billtoaddressid for billing addresses, shiptoaddressid for shipping). When you update an account’s address, CRM updates the associated customeraddress record and updates the account’s lookup field to point to that updated address. Our job is to copy that lookup reference to all linked contacts.

Full Plugin Code Snippet

Here’s the complete code for your Execute method, with comments explaining each step:

using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Collections.Generic;

public class SyncAccountAddressToContacts : IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        // Grab core CRM services from the provider
        IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
        IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
        IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

        try
        {
            // Only run for Account Update operations
            if (context.MessageName != "Update" || context.PrimaryEntityName != "account")
                return;

            // Get the updated account record from the plugin context
            Entity updatedAccount = (Entity)context.InputParameters["Target"];

            // Target the billing address here - swap with shiptoaddressid if syncing shipping addresses
            Guid? accountAddressId = updatedAccount.GetAttributeValue<EntityReference>("billtoaddressid")?.Id;
            
            // Skip if no address was set on the account
            if (!accountAddressId.HasValue)
                return;

            // Query all contacts linked to this account
            QueryExpression contactQuery = new QueryExpression("contact")
            {
                ColumnSet = new ColumnSet("contactid", "billtoaddressid"), // Only fetch needed fields
                Criteria = new FilterExpression
                {
                    Conditions =
                    {
                        new ConditionExpression("parentcustomerid", ConditionOperator.Equal, context.PrimaryEntityId)
                    }
                }
            };

            EntityCollection relatedContacts = service.RetrieveMultiple(contactQuery);
            if (relatedContacts.Entities.Count == 0)
                return;

            // Prepare contacts for update (skip if address is already matching)
            List<Entity> contactsToUpdate = new List<Entity>();
            foreach (Entity contact in relatedContacts.Entities)
            {
                Guid? currentContactAddressId = contact.GetAttributeValue<EntityReference>("billtoaddressid")?.Id;
                if (currentContactAddressId != accountAddressId)
                {
                    Entity contactUpdate = new Entity("contact", contact.Id);
                    contactUpdate["billtoaddressid"] = new EntityReference("customeraddress", accountAddressId.Value);
                    contactsToUpdate.Add(contactUpdate);
                }
            }

            // Batch update for efficiency (critical if you have many contacts)
            if (contactsToUpdate.Count > 0)
            {
                ExecuteMultipleRequest batchRequest = new ExecuteMultipleRequest
                {
                    Settings = new ExecuteMultipleSettings
                    {
                        ContinueOnError = false,
                        ReturnResponses = false
                    },
                    Requests = new OrganizationRequestCollection()
                };

                foreach (Entity contact in contactsToUpdate)
                {
                    batchRequest.Requests.Add(new UpdateRequest { Target = contact });
                }

                service.Execute(batchRequest);
            }
        }
        catch (Exception ex)
        {
            // Throw a meaningful error for debugging
            throw new InvalidPluginExecutionException($"Failed to sync account address to contacts: {ex.Message}", ex);
        }
    }
}

Important Setup Notes

  • Plugin Registration: Register this plugin on the account entity’s Update message. Set Filtering Attributes to billtoaddressid (or shiptoaddressid if syncing shipping addresses) so it only runs when the address is actually changed.
  • Permissions: Ensure the plugin’s execution user has:
    • Read/Write access to account and contact entities
    • Read access to customeraddress entities
  • Address Type: To sync shipping addresses instead, replace all instances of billtoaddressid with shiptoaddressid in the code.
  • Batch Updates: Using ExecuteMultipleRequest is far more efficient than individual UpdateRequest calls, especially if the account has dozens/hundreds of linked contacts.

内容的提问来源于stack exchange,提问作者Mike Bradley

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:12:47