Dynamics 365 CRM Online-插件仅每隔一次触发执行更新

时间:2018-06-19 14:12:33

标签: c# dynamics-crm microsoft-dynamics dynamics-crm-online

更新 我从该论坛以及Dynamics论坛中获取了一些信息,并且我的代码可以正常工作。代码中的主要问题是我只查看了preImage,但是在大多数情况下,这三个值之一将被更新,这意味着我无法针对该特定字段的preImage。我更改了逻辑以使用Collection属性(更新值)(如果已更新),但是使用PreImage值(如果未更新)-这使代码起作用,并且每次都会触发更新-不再需要触发插件两次!这是更新后的代码-比原始代码更有效,更简洁(向下滚动以查看旧的/无效的代码)。我还添加了一些评论,以使其更易于理解。感谢所有人的帮助(在SO和Dynamics论坛上都是如此!)

using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Crm.Sdk.Messages;
using System.ServiceModel;
using System.Data.SqlClient;
using System.Threading.Tasks;

namespace CLIENTNTE
{
    public class NTEExceedance : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service = factory.CreateOrganizationService(context.UserId);
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));


            Decimal nte_percent = 0;
            Decimal subtotalDecimal = 0;
            Decimal nteDecimal = 0;
            Decimal amountDiffDecimal = 0;
            Decimal percentDifference = 0;
            try
            {

                if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
                {
                    Entity entity = (Entity)context.InputParameters["Target"];
                    //if entity is not Work Order, return.  Prevents plugin firing on wrong entity (in case of wrong registration in plugin registration tool)
                    if (entity.LogicalName != "msdyn_workorder")
                    {
                        return;
                    }
                    //get preimage of WO Entity
                    Entity preMessageImage = (Entity)context.PreEntityImages["WONTEPreImage"];

                    //logic for when updated attribute is NTE Amount
                    if (entity.Attributes.Contains("CLIENT_nteamount") == true)
                    {
                        nteDecimal = entity.GetAttributeValue<Money>("CLIENT_nteamount").Value;
                    }
                    else
                    {
                        nteDecimal = preMessageImage.GetAttributeValue<Money>("CLIENT_nteamount").Value;
                    }
                    //logic for when updated attribute is NTE Percent
                    if (entity.Attributes.Contains("CLIENT_ntepercent") == true)
                    {
                        nte_percent = entity.GetAttributeValue<Decimal>("CLIENT_ntepercent");
                    }
                    else
                    {
                        nte_percent = preMessageImage.GetAttributeValue<Decimal>("CLIENT_ntepercent");
                    }
                    //logic for when updated attribute is Estimate Subtotal Amount
                    if (entity.Attributes.Contains("msdyn_estimatesubtotalamount") == true)
                    {
                        subtotalDecimal = entity.GetAttributeValue<Money>("msdyn_estimatesubtotalamount").Value;
                    }
                    else
                    {
                        subtotalDecimal = preMessageImage.GetAttributeValue<Money>("msdyn_estimatesubtotalamount").Value;
                    }

                    //calculation of Amount Difference, and Percent Difference
                    amountDiffDecimal = (subtotalDecimal - nteDecimal);
                    percentDifference = ((amountDiffDecimal / nteDecimal) * 100);

                    //Comparison logic to update the NTE Exceeded flag
                    if (percentDifference > nte_percent)
                    {
                        entity["CLIENT_nteexceeded"] = true;
                    }
                    if (percentDifference <= nte_percent)
                    {
                        entity["CLIENT_nteexceeded"] = false;
                    }
                }
            }
            catch (FaultException<OrganizationServiceFault> e)
            {
                //write errors to the CRM Plugin Trace Log
                tracingService.Trace("CLIENTPlugin - Update NTEExceededNonCalc: {0}", e.ToString());
                //Throw error through UI
                throw new InvalidPluginExecutionException("Error, Please See Plugin Log");
            }
        }
    }
}

原始帖子 再回来吧!昨天,我意识到我不使用PreImage来获取未包含在更新的属性集合中的值的错误-SCORE!现在,插件可以工作,但仅在我触发插件时每隔一次就可以工作。

因此,似乎插件实际上正在启动(我可以在“设置”>“插件配置文件”中看到插件配置文件),但是没有执行我需要的更新,直到第二次触发插件为止。这似乎发生在我正在监听的所有3个属性上,并且每个属性都需要更新两次(例如,如果我更新了属性1,则插件不会更新我的值,如果我随后更新了属性2,插件仍然不会更新我的值,直到再次重新更新属性1或属性2为止)。在我分析/调试代码并逐步执行代码时,我可以看到if语句被命中,并且更新了实体字段的代码行也正在执行-但由于某种原因,它没有设置值( CLIENT_nteexceeded = true或false),直到我第二次触发它为止。如果它根本不更新实体记录值,那将更有意义,而且我缺少某种类型的“更新”消息(我曾使用过service.Entity.Update(),但似乎没有应用于此插件)

我对CRMDEV还是一个新手,所以请原谅这个愚蠢的问题。对我来说,这似乎是一个非常愚蠢的问题,这肯定是我所缺少的小事情。关于为什么这迫使我两次触发代码以执行更新的任何想法?

这是插件步骤的配置。这三个过滤器属性是代码中引用的属性。同样,插件工作正常,只是不会每次都更新记录。 enter image description here

下面的代码(删除了对客户名称的引用)

using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Crm.Sdk.Messages;
using System.ServiceModel;
using System.Data.SqlClient;
using System.Threading.Tasks;

namespace CLIENTNTE
{
    public class NTEExceedance : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service = factory.CreateOrganizationService(context.UserId);
            //Extract the tracing service for use in debugging sandboxed plug-ins.
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

            Money subtotal = null;
            Money nte = null;
            Decimal nte_percent = 0;
            Decimal subtotalDecimal = 0;
            Decimal nteDecimal = 0;
            Decimal amountDiffDecimal = 0;
            Decimal percentDifference = 0;
            try
            {

                if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
                {
                    Entity entity = (Entity)context.InputParameters["Target"];
                    if (entity.LogicalName == "msdyn_workorder")
                    {
                        //code fires onChange of NTE Amount (same logic will apply to NTE % and Est Subtotal Amount)
                        if (entity.Attributes.Contains("CLIENT_nteamount") == true)
                        {
                            //String NewValue = FieldValue(service, new Guid(entity["msdyn_workorderid"].ToString()));
                            // String NewSubTotal = FieldValue(service, new Guid(entity["msdyn_workorderid"].ToString()), entity["msdyn_estimatesubtotalamount"].ToString());
                            //String NewNTE = FieldValue(service, new Guid(entity["msdyn_workorderid"].ToString()), entity["CLIENT_nteamount"].ToString());
                            //String Newpercent = FieldValue(service, new Guid(entity["msdyn_workorderid"].ToString()), entity["CLIENT_ntepercent"].ToString());
                            if (context.PreEntityImages.Contains("WONTEPreImage") && context.PreEntityImages["WONTEPreImage"] is Entity)
                            {
                                Entity preMessageImage = (Entity)context.PreEntityImages["WONTEPreImage"];
                                // get topic field value before database update perform
                                //pretopic = (String)preMessageImage.Attributes["subject"];
                                subtotal = (Money)preMessageImage.Attributes["msdyn_estimatesubtotalamount"];
                                nte = (Money)preMessageImage.Attributes["CLIENT_nteamount"];
                                nte_percent = (Decimal)preMessageImage.Attributes["CLIENT_ntepercent"];
                            }
                            //old way of trying to get values NON IMAGE
                            //subtotal = (Money)entity.Attributes["msdyn_estimatesubtotalamount"];
                            //nte = (Money)entity.Attributes["CLIENT_nteamount"];
                            //nte_percent = (Decimal)entity.Attributes["CLIENT_ntepercent"];

                            subtotalDecimal = subtotal.Value;
                            nteDecimal = nte.Value;
                            amountDiffDecimal = (subtotalDecimal - nteDecimal);
                            percentDifference = ((amountDiffDecimal / nteDecimal) * 100);
                            if (percentDifference > nte_percent)
                            {
                                //know this snippet works
                                entity["CLIENT_nteexceeded"] = true;
                            }
                            if (percentDifference <= nte_percent)
                            {
                                //know this snippet works
                                entity["CLIENT_nteexceeded"] = false;
                            }
                        }
                        if (entity.Attributes.Contains("CLIENT_ntepercent") == true)
                        {
                            if (context.PreEntityImages.Contains("WONTEPreImage") && context.PreEntityImages["WONTEPreImage"] is Entity)
                            {
                                Entity preMessageImage = (Entity)context.PreEntityImages["WONTEPreImage"];
                                // get topic field value before database update perform
                                //pretopic = (String)preMessageImage.Attributes["subject"];
                                subtotal = (Money)preMessageImage.Attributes["msdyn_estimatesubtotalamount"];
                                nte = (Money)preMessageImage.Attributes["CLIENT_nteamount"];
                                nte_percent = (Decimal)preMessageImage.Attributes["CLIENT_ntepercent"];
                            }

                            //old way of trying to get values NON IMAGE
                            //subtotal = (Money)entity.Attributes["msdyn_estimatesubtotalamount"];
                            //nte = (Money)entity.Attributes["CLIENT_nteamount"];
                            //nte_percent = (Decimal)entity.Attributes["CLIENT_ntepercent"];
                            subtotalDecimal = subtotal.Value;
                            nteDecimal = nte.Value;
                            amountDiffDecimal = (subtotalDecimal - nteDecimal);
                            percentDifference = ((amountDiffDecimal / nteDecimal) * 100);

                            if (percentDifference > nte_percent)
                            {
                                //know this snippet works
                                entity["CLIENT_nteexceeded"] = true;
                            }
                            if (percentDifference <= nte_percent)
                            {
                                //know this snippet works
                                entity["CLIENT_nteexceeded"] = false;
                            }
                        }
                        if (entity.Attributes.Contains("msdyn_estimatesubtotalamount") == true)
                        { 
                            if (context.PreEntityImages.Contains("WONTEPreImage") && context.PreEntityImages["WONTEPreImage"] is Entity)
                            {
                                Entity preMessageImage = (Entity)context.PreEntityImages["WONTEPreImage"];
                                subtotal = (Money)preMessageImage.Attributes["msdyn_estimatesubtotalamount"];
                                nte = (Money)preMessageImage.Attributes["CLIENT_nteamount"];
                                nte_percent = (Decimal)preMessageImage.Attributes["CLIENT_ntepercent"];
                            }

                            //old way of trying to get values NON IMAGE
                            //subtotal = (Money)entity.Attributes["msdyn_estimatesubtotalamount"];
                            //nte = (Money)entity.Attributes["CLIENT_nteamount"];
                            //nte_percent = (Decimal)entity.Attributes["CLIENT_ntepercent"];

                            subtotalDecimal = subtotal.Value;
                            nteDecimal = nte.Value;
                            amountDiffDecimal = (subtotalDecimal - nteDecimal);
                            percentDifference = ((amountDiffDecimal / nteDecimal) * 100);

                            if (percentDifference > nte_percent)
                            {
                                //know this snippet works
                                entity["CLIENT_nteexceeded"] = true;
                            }
                            if (percentDifference <= nte_percent)
                            {
                                //know this snippet works
                                entity["CLIENT_nteexceeded"] = false;
                            }

                        }

                    }
                }

            }
            catch (FaultException<OrganizationServiceFault> e)
            {
                tracingService.Trace("CLIENTPlugin - Update NTEExceededNonCalc: {0}", e.ToString());
                throw e;
            }
        }
    }

}

2 个答案:

答案 0 :(得分:1)

我将帮助您了解CRM执行管道的工作方式。然后,您可以借助trace / Audit / profiler进行故障排除,以找出失败的地方。

基本上,您是在预验证/预操作阶段中,在数据库事务处理之前,截获CRM CRM中发生的service.Update()平台调用。然后根据业务需要进行数据处理,并在目标实体本身中设置额外的属性值。这避免了另一个显式的额外service.Update()调用和返回循环死锁。

如果有任何异常,则表示您正在登录跟踪并抛出该异常。我建议将其更改为InvalidPluginExecutionException,您将在UI弹出窗口中看到它。这将回滚事务,这意味着将不会保存数据。

此外,为了更好地理解-记录每个条件语句,变量值等,以查看发生问题的确切跟踪日志。

答案 1 :(得分:1)

更新/答案我从该论坛以及Dynamics论坛中获取了一些信息,并且我的代码可以正常工作。代码中的主要问题是我只查看了preImage,但是在大多数情况下,这三个值之一将被更新,这意味着我无法针对该特定字段的preImage。我更改了逻辑以使用Collection属性(更新值)(如果已更新),但是使用PreImage值(如果未更新)-这使代码起作用,并且每次都会触发更新-不再需要触发插件两次!这是更新后的代码-比原始代码更有效,更简洁(向下滚动以查看旧的/无效的代码)。我还添加了一些评论,以使其更易于理解。感谢所有人的帮助(在SO和Dynamics论坛上都是如此!)

using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Crm.Sdk.Messages;
using System.ServiceModel;
using System.Data.SqlClient;
using System.Threading.Tasks;

namespace CLIENTNTE
{
    public class NTEExceedance : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService service = factory.CreateOrganizationService(context.UserId);
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));


            Decimal nte_percent = 0;
            Decimal subtotalDecimal = 0;
            Decimal nteDecimal = 0;
            Decimal amountDiffDecimal = 0;
            Decimal percentDifference = 0;
            try
            {

                if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
                {
                    Entity entity = (Entity)context.InputParameters["Target"];
                    //if entity is not Work Order, return.  Prevents plugin firing on wrong entity (in case of wrong registration in plugin registration tool)
                    if (entity.LogicalName != "msdyn_workorder")
                    {
                        return;
                    }
                    //get preimage of WO Entity
                    Entity preMessageImage = (Entity)context.PreEntityImages["WONTEPreImage"];

                    //logic for when updated attribute is NTE Amount
                    if (entity.Attributes.Contains("CLIENT_nteamount") == true)
                    {
                        nteDecimal = entity.GetAttributeValue<Money>("CLIENT_nteamount").Value;
                    }
                    else
                    {
                        nteDecimal = preMessageImage.GetAttributeValue<Money>("CLIENT_nteamount").Value;
                    }
                    //logic for when updated attribute is NTE Percent
                    if (entity.Attributes.Contains("CLIENT_ntepercent") == true)
                    {
                        nte_percent = entity.GetAttributeValue<Decimal>("CLIENT_ntepercent");
                    }
                    else
                    {
                        nte_percent = preMessageImage.GetAttributeValue<Decimal>("CLIENT_ntepercent");
                    }
                    //logic for when updated attribute is Estimate Subtotal Amount
                    if (entity.Attributes.Contains("msdyn_estimatesubtotalamount") == true)
                    {
                        subtotalDecimal = entity.GetAttributeValue<Money>("msdyn_estimatesubtotalamount").Value;
                    }
                    else
                    {
                        subtotalDecimal = preMessageImage.GetAttributeValue<Money>("msdyn_estimatesubtotalamount").Value;
                    }

                    //calculation of Amount Difference, and Percent Difference
                    amountDiffDecimal = (subtotalDecimal - nteDecimal);
                    percentDifference = ((amountDiffDecimal / nteDecimal) * 100);

                    //Comparison logic to update the NTE Exceeded flag
                    if (percentDifference > nte_percent)
                    {
                        entity["CLIENT_nteexceeded"] = true;
                    }
                    if (percentDifference <= nte_percent)
                    {
                        entity["CLIENT_nteexceeded"] = false;
                    }
                }
            }
            catch (FaultException<OrganizationServiceFault> e)
            {
                //write errors to the CRM Plugin Trace Log
                tracingService.Trace("CLIENTPlugin - Update NTEExceededNonCalc: {0}", e.ToString());
                //Throw error through UI
                throw new InvalidPluginExecutionException("Error, Please See Plugin Log");
            }
        }
    }
}