Skip to content

Instantly share code, notes, and snippets.

@melamriD365
Last active January 1, 2022 15:24
Show Gist options
  • Save melamriD365/7b009c2f67b87652cedcea77356cd7a8 to your computer and use it in GitHub Desktop.
Save melamriD365/7b009c2f67b87652cedcea77356cd7a8 to your computer and use it in GitHub Desktop.
Dynamics 365 CRM [Dataverse] - How to cancel of the merge cascade for a given relationship ? (CancelMergeForChilds_PreOperation)
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_PreOperation Plugin.
/// </summary>
public class CancelMergeForChilds_PreOperation : PluginBase
{
/// <summary>
/// Initializes a new instance of the <see cref="CancelMergeForChilds_PreOperation"/> 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_PreOperation(string unsecure, string secure)
: base(typeof(CancelMergeForChilds_PreOperation))
{
// 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;
try
{
// 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.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)
{
var tmpId = currentUserService.Create(new Entity(master.LogicalName));
var tmp = new Entity(master.LogicalName, tmpId);
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 = sub.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, tmp.Id);
currentUserService.Update(child);
}
}
context.SharedVariables.Add("tmp", tmp);
context.SharedVariables.Add("configs", configs);
}
}
}
// Only throw an InvalidPluginExecutionException. Please Refer https://go.microsoft.com/fwlink/?linkid=2153829.
catch (Exception ex)
{
tracingService?.Trace("An error occurred executing Plugin MergePoc.Plugins.CancelMergeForChilds_PreOperation : {0}", ex.ToString());
throw new InvalidPluginExecutionException("An error occurred executing Plugin MergePoc.Plugins.CancelMergeForChilds_PreOperation .", 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