Dynamics CRM检测删除消息是否为级联删除

时间:2014-02-17 09:57:57

标签: dynamics-crm-2011 dynamics-crm dynamics-crm-2013

我有一个自定义工作流活动,可以在删除自定义实体时运行 我需要确定删除邮件是从父实体(机会)进行常规删除还是级联删除。

我发现即使存在级联删除,父实体也存在。

我还可以查看删除是否是级联删除的结果?

我需要获取此信息,因为自定义实体正在更新删除时的父实体 - 它应该仅在删除不是级联删除的结果时更新,否则发生SQL错误,这可能是由于工作流程正在尝试更新事务中正在删除的记录。

修改

Tanguy T asked the same question here,但未解决。

3 个答案:

答案 0 :(得分:1)

我相信您可以检查工作流上下文的ParentContext成员。如果它为null或者ParentContext的Message不等于Delete - 这意味着这不是Cascade Delete。检查this article

答案 1 :(得分:1)

将您的工作流程更改为插件,然后您应该能够使用Plugin Shared Variables来确定该信息。只需将一个Pre Event插件添加到父实体,指定这是父级联删除的一部分。然后在子插件中,只检查该变量是否存在,如果不存在,则表示它不是级联。

答案 2 :(得分:1)

我结束了

  • 将关系更改为参考
  • 添加一个异步工作流,该工作流将子实体查找的更改更改为其父
  • 查询是强制性的
  • 如果该字段为空,则检查工作流程,如果
  • ,则调用以下自定义工作流程活动

此自定义工作流活动会删除当前记录:

public class DeleteCurrentRecord : CodeActivity
{
    protected override void Execute(CodeActivityContext context)
    {
        if (context == null)
        {
            throw new InvalidPluginExecutionException("Workflow context error. Please retry the operation.");
        }
        using (var workflowContext = new WorkflowContext(context))
        {
            DeleteRecord(workflowContext, context);
        }
    }
    public void DeleteRecord(WorkflowContext context, CodeActivityContext activityContext)
    {
        var targetId = context.Target != null ? context.Target.Id : context.TargetReference.Id;
        var targetName = context.Target != null ? context.Target.LogicalName : context.TargetReference.LogicalName;
        context.Service.Delete(targetName, targetId);
    }
}

这是我编写的帮助程序类,它从CodeActivityContext获取我需要的所有内容 它只是为每个工作流程节省了相同的锅炉铭牌代码 我还可以在控制台应用程序中构造一个对象来在本地测试工作流:

/* WorkflowContext is a helper class that I wrote that gets all the CRM services
 * and everything else from a CodeActivityContext
 * I then pass an instance of it to methods
 * I add properties to WorkflowContext as needed
 * */
/* Contains objects that are taken from CodeActivityContext
 * */
public class WorkflowContext : IDisposable
{
    public IOrganizationService Service { get; private set; }
    public Entity Target { get; private set; }
    public EntityReference TargetReference { get; private set; }
    public Context Linq { get; private set; }
    public IWorkflowContext CurrentContext { get; set; }
    public string PrimaryEntityName { get; set; }
    public int Depth { get; set; }
    public WorkflowContext(CodeActivityContext activityContext)
    {
        IWorkflowContext context = activityContext.GetExtension<IWorkflowContext>();
        CurrentContext = context;
        PrimaryEntityName = context.PrimaryEntityName;
        Depth = context.Depth;
        IOrganizationServiceFactory factory = activityContext.GetExtension<IOrganizationServiceFactory>();
        if (context.InputParameters.Contains("Target")) // On demand workflows do not have target
        {
            if (context.InputParameters["Target"].GetType() == typeof(Entity))
                Target = (Entity)context.InputParameters["Target"];
            else if (context.InputParameters["Target"].GetType() == typeof(EntityReference)) // delete and some other operations are EntityReference
                TargetReference = (EntityReference)context.InputParameters["Target"];
        }
        Service = factory.CreateOrganizationService(context.InitiatingUserId);
        Linq = new Context(Service);
    }
    // Constructor for testing
    public WorkflowContext(IOrganizationService service, Context linq, EntityReference targetReference, Entity target, bool inTransaction)
    {
        this.Service = service;
        this.Linq = linq;
        this.TargetReference = targetReference;
        this.Target = target;
    }
    public void Dispose()
    {
        Linq.Dispose();
    }
}