【问题标题】:Dynamics 365 CRM Online - Use a Field that is NOT in collection (Hasn't been updated)Dynamics 365 CRM Online - 使用不在集合中的字段(尚未更新)
【发布时间】:2018-06-18 18:30:23
【问题描述】:

总体问题是:如何在 D365 CRM 插件中访问不在我的集合中(尚未更新)的实体变量?

我已经为此苦苦挣扎了很长一段时间,现在,我求助于论坛大神们,以帮助了解这里发生的事情。

我在 D365 CRM (v9.0) 中对工作订单实体进行了自定义。本质上,每当更新三个字段之一时,我每次都需要执行相同的逻辑。无论出于何种原因,只有在一次操作中更新所有三个字段时,该插件才会起作用。如果我只是更新一个,我会得到“key not present in dictionary”错误,表示我的变量不在当前集合中。

我试图将我的“包含”检查更改为包含 XYZ ||包含ABC ||包含 123,但立即失败。然后,我尝试将这些条件中的每一个嵌套在一起,但是当然,最低的嵌套不会被触及。然后我尝试取消嵌套,并单独尝试每个“包含”检查,然后继续在所有三个 if 块中执行逻辑。到目前为止,这一切都让我失望了。

我在这里缺少什么吗?出于测试目的,我将它设置为触发所有属性(不仅仅是我想要检查的三个),但即使这样对我来说也失败了。我还与一位在 CRM 开发方面经验丰富的同事进行了交谈,您可以在“FieldValue”函数调用中看到一些工件(尽管我已经删除了 FieldValue此代码片段中的函数)。

我是 CRM 开发的新手,但自 4.0 以来一直在 MSCRM 中工作。
非常感谢任何建议。

总体问题是:如何在 D365 CRM 插件中访问不在我的集合中(尚未更新)的实体变量?

以下代码,删除了对我客户姓名的引用:

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)
                        {


                            //trying to use the FieldValue function to grab these fields into collection, commented out for now
                            //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());

                            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);

                            // decimal percentDifference = 100;
                            //decimal nte_percent = 50;
                            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)
                        {
                            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);

                            // decimal percentDifference = 100;
                            //decimal nte_percent = 50;
                            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)
                        {


                            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);

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


                            /*
                            Money m = (Money)entity.Attributes["new_evalmoneyvalue"];

                            decimal actualAmount = m.Value;

                            entity["new_evaldecimal"] = actualAmount;

                            entity["new_evalmoneyvalue"] = new Money((decimal)actualAmount * 2);
                            */
                        }

                    }
                }



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

    }

}

【问题讨论】:

  • 逻辑非常简单 - 如果我在更新操作中包含所有 3 个变量(通过 UI),它会按预期触发。让我感到困惑的是,无论数据是否在“集合”中,都很难触发逻辑 - 它存在于实体中,我正在从实体记录中获取它!我还计划将所有这三个字段都设为必填项。这需要一个插件来允许在不打开表单的情况下进行操作(Biz Rules 和 JScript 都可以满足这个要求)。

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


【解决方案1】:

如何在 D365 CRM 插件中访问不在我的集合中(尚未更新)的实体变量?

答案:图像(前图像或后图像)

在更新步骤中注册具有必要属性的图像,这样您将获得整个实体对象或您标记的每个属性。基本上它是一个有效的平台检索调用并在上下文本身为您服务。

例如,在您的情况下,使用 PreImage(所有 3 个属性)注册 Post-Update 步骤。所以修改后的属性会在(Entity)context.InputParameters["Target"]。可以从(Entity)context.PreEntityImages["Image"] 使用未修改的属性。 Read more

Also Contains 可能总是会出现,因此请检查 Money/Decimal 字段,如 here 解释的那样。

Money myMoneyField = (Money)EntityObject.GetAttributeValue<Money>(Amount);

decimal actualAmount;

if (myMoneyField != null)
{
    actualAmount = myMoneyField.Value;
}

现在您拥有交易前后的属性值,因此您决定并存储要在计算中使用的值。

Entity orderEntity = (Entity)context.InputParameters["Target"];
Entity preOrderEntity = (Entity)context.PreEntityImages["Image"];
Decimal preNTEamount = preOrderEntity.GetAttributeValue<Money>("CLIENT_nteamount") != null ? ((Money)preOrderEntity.GetAttributeValue<Money>("CLIENT_nteamount")).Value : 0;
Decimal newNTEamount = orderEntity.GetAttributeValue<Money>("CLIENT_nteamount") != null ? ((Money)orderEntity.GetAttributeValue<Money>("CLIENT_nteamount")).Value : preNTEamount;

【讨论】:

  • 阿伦 - 感谢您的快速回复!我转移到我的代码的 Pre-Image 版本,它似乎按预期工作。谢谢!作为后续行动(我可能会被回避,并且必须在这里发布一个新线程......) - 我的插件只会在我触发它的所有其他时间触发。意思是,我通过更改三个字段之一来触发它,它不会更新记录中的目标字段。当我再次触发它时,通过更改相同字段的值,插件触发,预期结果随之而来。关于为什么会发生这种情况的任何想法?再次感谢伙计!
  • @BrianFrick 没问题。我的猜测是插件每次都会触发,但不会在某种意义上更新字段,可能存在一些逻辑缺陷。尝试使用分析器调试代码。
  • 谢谢伙计。我已经调试/分析了几次,但没有任何事情发生在我身上(所有变量看起来都很好,看起来应该设置我的是/否,但没有)但是伙计,我花了很多时间试图在没有预先设置的情况下做到这一点-image,我认为是时候收工了,并在清晨通过新的调试会话重新恢复。再次感谢您花时间写下您的想法 - 非常有帮助!
猜你喜欢
  • 2018-02-07
  • 1970-01-01
  • 2019-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多