Skip to content

Instantly share code, notes, and snippets.

Last active January 1, 2022 15:23
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save melamriD365/72186eb0dbc627306941d07c62b22fe4 to your computer and use it in GitHub Desktop.
Dynamics 365 CRM [Dataverse] - How to cancel of the merge cascade for a given relationship ? (Post-Operation Plugin)
using System;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Metadata;
using Microsoft.Xrm.Sdk.Query;
namespace MergePoc.Plugins
/// <summary>
/// CancelMergeForChilds_PostOperation Plugin.
/// </summary>
public class CancelMergeForChilds_PostOperation: PluginBase
/// <summary>
/// Initializes a new instance of the <see cref="CancelMergeForChilds_PostOperation"/> class.
/// </summary>
/// <param name="unsecure">Contains public (unsecured) configuration information.</param>
/// <param name="secure">Contains non-public (secured) configuration information.
/// When using Microsoft Dynamics 365 for Outlook with Offline Access,
/// the secure string is not passed to a plug-in that executes while the client is offline.</param>
public CancelMergeForChilds_PostOperation(string unsecure, string secure)
: base(typeof(CancelMergeForChilds_PostOperation))
// TODO: Implement your custom configuration handling.
/// <summary>
/// Main entry point for he business logic that the plug-in is to execute.
/// </summary>
/// <param name="localContext">The <see cref="LocalPluginContext"/> which contains the
/// <see cref="IPluginExecutionContext"/>,
/// <see cref="IOrganizationService"/>
/// and <see cref="ITracingService"/>
/// </param>
/// <remarks>
/// For improved performance, Microsoft Dynamics 365 caches plug-in instances.
/// The plug-in's Execute method should be written to be stateless as the constructor
/// is not called for every invocation of the plug-in. Also, multiple system threads
/// could execute the plug-in at the same time. All per invocation state information
/// is stored in the context. This means that you should not use global variables in plug-ins.
/// </remarks>
protected override void ExecuteCdsPlugin(ILocalPluginContext localContext)
if (localContext == null)
throw new InvalidPluginExecutionException(nameof(localContext));
// Obtain the tracing service
ITracingService tracingService = localContext.TracingService;
// Obtain the execution context from the service provider.
IPluginExecutionContext context = (IPluginExecutionContext)localContext.PluginExecutionContext;
// Obtain the organization service reference for web service calls.
IOrganizationService currentUserService = localContext.CurrentUserService;
if (context.SharedVariables.Contains("tmp"))
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is EntityReference)
EntityReference master = (EntityReference)context.InputParameters["Target"];
EntityReference sub = new EntityReference(master.LogicalName, (Guid)context.InputParameters["SubordinateId"]);
EntityCollection configs = getConfigs(currentUserService, master.LogicalName);
if (configs.Entities.Count > 0)
Entity tmp = (Entity)context.SharedVariables["tmp"];
foreach (var config in configs.Entities)
var childLogicalName = config.GetAttributeValue<string>("uma_childentity");
var relationshipLogicalName = config.GetAttributeValue<string>("uma_relationship");
RetrieveRelationshipRequest retrieveRelationShipRequest = new RetrieveRelationshipRequest { Name = relationshipLogicalName };
RetrieveRelationshipResponse retrieveRelationShipResponse = (RetrieveRelationshipResponse)currentUserService.Execute(retrieveRelationShipRequest);
OneToManyRelationshipMetadata meta = (OneToManyRelationshipMetadata)retrieveRelationShipResponse.RelationshipMetadata;
var from = meta.ReferencedAttribute;
var to = meta.ReferencingAttribute;
var query_parentid = tmp.Id;
var query = new QueryExpression(meta.ReferencingEntity);
query.ColumnSet = new ColumnSet(to);
query.Criteria.AddCondition(to, ConditionOperator.Equal, query_parentid);
EntityCollection childs = currentUserService.RetrieveMultiple(query);
foreach (var child in childs.Entities)
child[to] = new EntityReference(tmp.LogicalName, sub.Id);
currentUserService.Delete(tmp.LogicalName, tmp.Id);
// Only throw an InvalidPluginExecutionException. Please Refer
catch (Exception ex)
tracingService?.Trace("An error occurred executing Plugin MergePoc.Plugins.CancelMergeForChilds_PostOperation : {0}", ex.ToString());
throw new InvalidPluginExecutionException("An error occurred executing Plugin MergePoc.Plugins.CancelMergeForChilds_PostOperation .", ex);
private EntityCollection getConfigs(IOrganizationService currentUserService, string MasterLogicalName)
var query_uma_parententity = MasterLogicalName;
var query = new QueryExpression("uma_mergecascadeconfiguration");
query.ColumnSet.AllColumns = true;
query.Criteria.AddCondition("uma_parententity", ConditionOperator.Equal, query_uma_parententity);
return currentUserService.RetrieveMultiple(query);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment