![](/img/trans.png)
[英]How to retrieve records in CRM Online through plugin in Dynamics CRM 365 On-Premise
[英]Dynamics 365 CRM Online - Plugin Only Performs Update Every Other Time it is Triggered
更新我從該論壇以及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還是比較陌生,所以請原諒這個愚蠢的問題。 對我來說,這似乎是一個非常愚蠢的問題,這肯定是我所缺少的小事情。 關於為什么這迫使我兩次觸發代碼以執行更新的任何想法?
這是插件步驟的配置。 這三個過濾器屬性是代碼中引用的屬性。 同樣,插件工作正常,只是不會每次都更新記錄。
以下代碼(刪除了對客戶名稱的引用)
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;
}
}
}
}
我將幫助您了解CRM執行管道的工作方式。 然后,您可以在trace / Audit / profiler的幫助下進行故障排除,以找出失敗的地方。
基本上,您是在預驗證/預操作階段中,在DB事務之前攔截從CRM UI發生的service.Update()
平台調用。 然后根據業務需要進行數據處理,並在目標實體本身中設置額外的屬性值。 這避免了另一個顯式的額外service.Update()
調用並反過來循環死鎖。
如果有任何異常,則您正在登錄跟蹤並拋出該異常。 我建議將其更改為InvalidPluginExecutionException
,您將在UI彈出窗口中看到該InvalidPluginExecutionException
。 這將回滾事務,這意味着不會保存數據。
此外,為了更好地理解-記錄每個條件語句,變量值等,以查看發生問題的確切跟蹤日志。
更新/回答我從該論壇以及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");
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.