針對 Dataverse 外掛程式進行疑難解答

本文包含外掛程式執行期間可能發生的錯誤,或與外掛程式相關的 Dataverse 錯誤,以及如何避免或修正這些錯誤的相關信息。

錯誤「無法完成時間轉換」

錯誤碼: -2147220956
錯誤訊息:無法完成轉換,因為提供的 DataTime 未正確設定 Kind 屬性。 例如,當 Kind 屬性為 DateTimeKind.Local 時,來源時區必須是 TimeZoneInfo.Local。

在呼叫外掛程式程式代碼時 TimeZoneInfo.ConvertTimeToUtc(DateTime, TimeZoneInfo) ,可能會發生此錯誤,以將[金鑰] 或 [Volgograd] 時區中的值轉換成 DateTime 國際標準時間 (UTC) 。

此錯誤是由已知的產品限制所造成,而且目前沒有任何因應措施。

如需詳細資訊,請 參閱指定使用者的時區設定

錯誤「沙盒背景工作進程損毀」

錯誤碼: -2147204723
錯誤訊息:外掛程式執行失敗,因為沙箱背景工作進程損毀。 這通常是因為外掛程式代碼發生錯誤。

此錯誤只是表示執行外掛程式程式代碼的背景工作進程損毀。 您的外掛程式可能是當機的原因,但也可能是另一個同時為組織執行的外掛程式。 由於進程損毀,因此我們無法擷取其損毀原因的更具體資訊。 但是在檢查事實之後損毀傾印中的數據之後,我們發現此錯誤通常是因為下列四個原因之一所造成:

外掛程式中未處理的例外狀況

當您撰寫外掛程式時,應該嘗試預期哪些作業可能會失敗,並將它們包裝在 try-catch 區塊中。 發生錯誤時,您應該使用 InvalidPluginExecutionException 類別,以對使用者有意義的錯誤正常終止作業。

如需詳細資訊,請 參閱處理外掛程式中的例外狀況

此例外狀況的常見案例是使用 HttpClient.SendAsyncHttpClient.GetAsync 方法時。 這些 HttpClient 方法是傳回 Task 的異步操作。 若要在需要同步程式代碼的外掛程式中工作,人們可能會使用 Task<TResult>。Result 屬性。 發生錯誤時, 會 Result 傳回 AggregateException。 會 AggregateException 將多個失敗合併成單一例外狀況,這可能很難處理。 更好的設計是使用 Task<TResult>。GetAuditer () GetResult () ,因為它會將結果傳播為導致失敗的特定錯誤。

下列範例示範使用 HttpClient.GetAsync 方法管理例外狀況和輸出呼叫的正確方式。 此外掛程式會嘗試針對已註冊的步驟,取得不安全設定中所設定 Uri 的回應文字。

using Microsoft.Xrm.Sdk;
using System;
using System.Net.Http;

namespace ErrorRepro
{
    public class AsyncError : IPlugin
    {
        private readonly string webAddress;

        public AsyncError(string unsecureConfig)
        {
            if (string.IsNullOrEmpty(unsecureConfig)) {
                throw new InvalidPluginExecutionException("The ErrorRepro.AsyncError plug-in requires that a Url be set in the unsecure configuration for the step registration.");
            }
            webAddress = unsecureConfig;

        }

        public void Execute(IServiceProvider serviceProvider)
        {
            ITracingService tracingService =
            (ITracingService)serviceProvider.GetService(typeof(ITracingService));

            tracingService.Trace($"Starting ErrorRepro.AsyncError");
            tracingService.Trace($"Sending web request to {webAddress}");

            try
            {
                string responseText = GetWebResponse(webAddress, tracingService);
                tracingService.Trace($"Result: {responseText.Substring(0, 100)}");
            }
            catch (Exception ex)
            {
                tracingService.Trace($"Error: ErrorRepro.AsyncError {ex.Message}");
                throw new InvalidPluginExecutionException(ex.Message);
            }
            tracingService.Trace($"Ending ErrorRepro.AsyncError");
        }

        //Gets the text response of an outbound web service call
        public string GetWebResponse(string webAddress, ITracingService tracingService)
        {
            try
            {
                using (HttpClient client = new HttpClient())
                {
                    client.Timeout = TimeSpan.FromMilliseconds(15000); //15 seconds
                    client.DefaultRequestHeaders.ConnectionClose = true; //Set KeepAlive to false

                    HttpResponseMessage response = client.GetAsync(webAddress).GetAwaiter().GetResult(); //Make sure it is synchronous
                    response.EnsureSuccessStatusCode();

                    tracingService.Trace($"ErrorRepro.AsyncError.GetWebResponse succeeded.");

                    string responseContent = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); //Make sure it is synchronous

                    tracingService.Trace($"ErrorRepro.AsyncError.GetWebResponse responseContent parsed successfully.");

                    return responseContent;

                }
            }
            catch (Exception ex)
            {
                //Capture the inner exception message if it exists.
                // It should have a more specific detail.
                string innerExceptionMessage = string.Empty;
                if (ex.InnerException != null) {
                    innerExceptionMessage = ex.InnerException.Message;
                }

                tracingService.Trace($"Error in ErrorRepro.AsyncError : {ex.Message} InnerException: {innerExceptionMessage}");
                if (!string.IsNullOrEmpty(innerExceptionMessage))
                {
                    throw new Exception($"A call to an external web service failed. {innerExceptionMessage}", ex);
                }

                throw new Exception("A call to an external web service failed.", ex);
            }
        }
    }
}

使用線程將線程排入佇列,在線程委派中不使用 try/catch

您不應該在外掛程式中使用平行執行模式。最佳做法文章會說明此反模式: 請勿在外掛程式和工作流程活動內使用平行執行。 使用這些模式可能會導致在同步外掛程式中管理交易時發生問題。 不過,不使用這些模式的另一個原因是,在線程委派的區塊外部 try/catch 完成的任何工作,都可能會損毀背景工作進程。

重要事項

當背景工作進程當機時,您的外掛程式和其他目前在該進程中執行的外掛程式將會終止。 這包括您不擁有或維護的外掛程式。

Application Insights 至救援

在過去,無法從損毀的背景工作進程取得堆疊追蹤或其他未處理外掛程式例外狀況的執行資訊。 不過,Dataverse 現在支援將執行失敗記錄到 Application Insights。 若要啟用此函式,您可以將 Application Insights 連結至您的外掛程式註冊所在的環境。 鏈接之後,即會自動發生外掛程式損毀的記錄。

如需詳細資訊,請參閱將 數據導出至 Application Insights

連結 Application Insights 環境之後,工作程式損毀的下列數據將可用於疑難解答問題。

Application Insights 外掛程式損毀報告的範例。

若要流覽至 Application Insights 中的損毀報告,請遵循下列步驟:

  1. 將 Application Insights 連結至您的環境
  2. 等到外掛程式例外狀況導致背景工作進程發生當機錯誤為止。
  3. Power Platform 系統管理中心中,流覽至 Application Insights。
  4. 在 [Application Insights] 頁面上,選取左面板中的 [ 失敗 ]。
  5. 在 [ 失敗] 頁面上,選取 [ 例外狀況]
  6. [例外狀況問題標識符] 下方的 [ 整體 ] 列表中,選取 [Microsoft.PowerPlatform.Dataverse.Plugin.PluginWorkerCrashException]
  7. 在頁面右側的 [ 整體] 底下,選取 [PluginWorkerCrashException]。 您現在會看到所有已記錄背景工作進程損毀例外狀況的詳細數據。
  8. 搜尋 在左面板中選取所需的例外狀況,而且例外狀況詳細數據報告會顯示在頁面右側 (如需範例) ,請參閱上述螢幕快照。
  9. 若要存取堆疊追蹤,請展開報表中的 CrashDetails

外掛程式中的堆疊溢位錯誤

這種類型的錯誤最常發生在您對外掛程式程式代碼進行一些變更之後。 有些人會使用自己的基類集合來簡化其開發體驗。 有時候這些錯誤源自於特定外掛程式相依的基類變更。

例如,沒有終止條件的遞歸呼叫,或未涵蓋所有案例的終止條件,可能會導致發生此錯誤。 如需詳細資訊,請參閱 StackOverflowException 類別 > 備註

您應該檢閱最近針對外掛程式套用的任何程式代碼變更,以及外掛程式程式代碼相依的任何其他程式代碼。

範例

下列外掛程式代碼會導致 StackOverflowException ,因為沒有限制的遞歸呼叫。 儘管使用追蹤並嘗試擷取錯誤,但不會傳回追蹤和錯誤,因為處理它們的背景工作進程已終止。

using Microsoft.Xrm.Sdk;
using System;

namespace ErrorRepro
{
    public class SOError : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            ITracingService tracingService =
           (ITracingService)serviceProvider.GetService(typeof(ITracingService));

            tracingService.Trace($"Starting ErrorRepro.SOError");

            try
            {
                tracingService.Trace($"Calling RecursiveMethodWithNoLimit to trigger StackOverflow error.");

                RecursiveMethodWithNoLimit(tracingService); //StackOverflowException occurs here.
            }
            catch (Exception ex)
            {
                //This trace will not be written
                tracingService.Trace($"Error in ErrorRepro.SOError {ex.Message}");

                //This error will never be thrown
                throw new InvalidPluginExecutionException($"Error in ErrorRepro.SOError. {ex.Message}");
            }

            //This trace will never be written
            tracingService.Trace($"Ending ErrorRepro.SOError");
        }

        public static void RecursiveMethodWithNoLimit(ITracingService tracingService)
        {
            tracingService.Trace($"Starting ErrorRepro.SOError.RecursiveMethodWithNoLimit");

            RecursiveMethodWithNoLimit(tracingService);

            tracingService.Trace($"Ending ErrorRepro.SOError.RecursiveMethodWithNoLimit");
        }
    }
}

在同步外掛程式步驟中,先前顯示的外掛程式程式代碼會在要求設定為 包含錯誤的其他詳細數據時,在 Web API 中傳回下列錯誤。

{
    "error": {
        "code": "0x8004418d",
        "message": "The plug-in execution failed because the Sandbox Worker process crashed. This is typically due to an error in the plug-in code.\r\nSystem.ServiceModel.CommunicationException: The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.\r\n   at Microsoft.Crm.Sandbox.SandboxWorkerProcess.Execute(SandboxCallInfo callInfo, SandboxPluginExecutionContext requestContext, Guid pluginAssemblyId, Int32 sourceHash, String assemblyName, Guid pluginTypeId, String pluginTypeName, String pluginConfiguration, String pluginSecureConfig, Boolean returnTraceInfo, Int64& wcfExecInMs, Int64& initializeInMs, Int64& trackCallInMs, Int64& trackGoodReturnInMs, Int64& waitInMs, Int64& taskStartDelay) +0x330: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #8503641A",
        "@Microsoft.PowerApps.CDS.ErrorDetails.ApiExceptionSourceKey": "Plugin/ErrorRepro.SOError, ErrorRepro, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c2bee3e550ec0851",
        "@Microsoft.PowerApps.CDS.ErrorDetails.ApiStepKey": "d5958631-b87e-eb11-a812-000d3a4f50a7",
        "@Microsoft.PowerApps.CDS.ErrorDetails.ApiDepthKey": "1",
        "@Microsoft.PowerApps.CDS.ErrorDetails.ApiActivityIdKey": "a3028bda-73c2-4eef-bcb5-157c5a4c323e",
        "@Microsoft.PowerApps.CDS.ErrorDetails.ApiPluginSolutionNameKey": "Active",
        "@Microsoft.PowerApps.CDS.ErrorDetails.ApiStepSolutionNameKey": "Active",
        "@Microsoft.PowerApps.CDS.ErrorDetails.ApiExceptionCategory": "SystemFailure",
        "@Microsoft.PowerApps.CDS.ErrorDetails.ApiExceptionMesageName": "SandboxWorkerNotAvailable",
        "@Microsoft.PowerApps.CDS.ErrorDetails.ApiExceptionHttpStatusCode": "500",
        "@Microsoft.PowerApps.CDS.HelpLink": "http://go.microsoft.com/fwlink/?LinkID=398563&error=Microsoft.Crm.CrmException%3a8004418d&client=platform",
        "@Microsoft.PowerApps.CDS.TraceText": "\r\n[ErrorRepro: ErrorRepro.SOError]\r\n[d5958631-b87e-eb11-a812-000d3a4f50a7: ErrorRepro.SOError: Create of account]\r\n\r\n",
        "@Microsoft.PowerApps.CDS.InnerError.Message": "The plug-in execution failed because the Sandbox Worker process crashed. This is typically due to an error in the plug-in code.\r\nSystem.ServiceModel.CommunicationException: The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.\r\n   at Microsoft.Crm.Sandbox.SandboxWorkerProcess.Execute(SandboxCallInfo callInfo, SandboxPluginExecutionContext requestContext, Guid pluginAssemblyId, Int32 sourceHash, String assemblyName, Guid pluginTypeId, String pluginTypeName, String pluginConfiguration, String pluginSecureConfig, Boolean returnTraceInfo, Int64& wcfExecInMs, Int64& initializeInMs, Int64& trackCallInMs, Int64& trackGoodReturnInMs, Int64& waitInMs, Int64& taskStartDelay) +0x330: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #8503641A"
    }
}

以下顯示如何在外掛程式追蹤記錄中記錄此錯誤:

Unhandled exception: 
Exception type: System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]
Message: The plug-in execution failed because the Sandbox Worker process crashed. This is typically due to an error in the plug-in code.
System.ServiceModel.CommunicationException: The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.
   at Microsoft.Crm.Sandbox.SandboxWorkerProcess.Execute(SandboxCallInfo callInfo, SandboxPluginExecutionContext requestContext, Guid pluginAssemblyId, Int32 sourceHash, String assemblyName, Guid pluginTypeId, String pluginTypeName, String pluginConfiguration, String pluginSecureConfig, Boolean returnTraceInfo, Int64& wcfExecInMs, Int64& initializeInMs, Int64& trackCallInMs, Int64& trackGoodReturnInMs, Int64& waitInMs, Int64& taskStartDelay) +0x330: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #4BC22433Detail: 
<OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
  <ActivityId>48c5818e-4912-42f0-b1b6-e3bbe7ae013d</ActivityId>
  <ErrorCode>-2147204723</ErrorCode>
  <ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
  <HelpLink i:nil="true" />
  <Message>The plug-in execution failed because the Sandbox Worker process crashed. This is typically due to an error in the plug-in code.
System.ServiceModel.CommunicationException: The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.
   at Microsoft.Crm.Sandbox.SandboxWorkerProcess.Execute(SandboxCallInfo callInfo, SandboxPluginExecutionContext requestContext, Guid pluginAssemblyId, Int32 sourceHash, String assemblyName, Guid pluginTypeId, String pluginTypeName, String pluginConfiguration, String pluginSecureConfig, Boolean returnTraceInfo, Int64&amp; wcfExecInMs, Int64&amp; initializeInMs, Int64&amp; trackCallInMs, Int64&amp; trackGoodReturnInMs, Int64&amp; waitInMs, Int64&amp; taskStartDelay) +0x330: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #4BC22433</Message>
  <Timestamp>2021-03-06T22:14:22.0629638Z</Timestamp>
  <ExceptionRetriable>false</ExceptionRetriable>
  <ExceptionSource>WorkerCommunication</ExceptionSource>
  <InnerFault i:nil="true" />
  <OriginalException>System.ServiceModel.CommunicationException: The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.

Server stack trace: 
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
   at Microsoft.Crm.Sandbox.SandboxWorkerProcess.Execute(SandboxCallInfo callInfo, SandboxPluginExecutionContext requestContext, Guid pluginAssemblyId, Int32 sourceHash, String assemblyName, Guid pluginTypeId, String pluginTypeName, String pluginConfiguration, String pluginSecureConfig, Boolean returnTraceInfo, Int64&amp; wcfExecInMs, Int64&amp; initializeInMs, Int64&amp; trackCallInMs, Int64&amp; trackGoodReturnInMs, Int64&amp; waitInMs, Int64&amp; taskStartDelay)</OriginalException>
  <TraceText i:nil="true" />
</OrganizationServiceFault>

背景工作進程達到記憶體限制

每個背景工作進程都有有限的記憶體數量。 在某些情況下,包含大量數據的多個並行作業可能會超過可用的記憶體,並導致進程背景工作當機。

RetrieveMultiple 與檔案數據

在此案例中,常見的案例是當外掛程式針對 RetrieveMultiple 要求包含檔案數據的作業執行時。 例如,擷取包含任何檔案附件的電子郵件時。 這類查詢中可能傳回的數據量無法預測,因為任何電子郵件都可能與任意數量的檔案附件相關,而且附件的大小可能會有所不同。

當多個類似性質的要求同時執行時,所需的記憶體數量就會變大。 如果記憶體數量超過限制,進程就會損毀。 防止這種情況的關鍵在於限制 RetrieveMultiple 包含具有相關檔案附件之實體的查詢。 使用 RetrieveMultiple擷取記錄,但使用個別 Retrieve 作業視需要擷取任何相關檔案。

記憶體流失

較不常見的案例是外掛程式中的程式代碼會流失記憶體。 當外掛程式不是以無狀態撰寫時,就會發生這種情況,這是另一個最佳做法。 如需詳細資訊,請 參閱將外掛程式實作開發為無狀態。 當外掛程式不是無狀態,而且嘗試持續將數據新增至如數位的具狀態屬性時,數據量會成長到使用所有可用記憶體的點。

交易錯誤

有兩種常見的交易相關錯誤類型:

錯誤碼: -2146893812
錯誤訊息:ISV 程式代碼減少開啟的交易計數。 自定義外掛程式不應攔截來自 OrganizationService 呼叫的例外狀況,並繼續處理。

錯誤碼: -2147220911
錯誤訊息:沒有作用中的交易。 此錯誤通常是由忽略服務呼叫錯誤並繼續處理的自定義外掛程式所造成。

注意事項

最近新增了最上層錯誤。 它應該會立即在包含問題的外掛程式內容中發生。 底部錯誤仍可能在不同的情況下發生,通常涉及自定義工作流程活動。 這可能是因為另一個外掛程式發生問題。

每當同步外掛程式內發生與數據作業相關的錯誤時,整個作業的交易都會結束。

如需詳細資訊,請 參閱 Microsoft Dataverse 中的可調整自定義設計

常見的原因是開發人員認為他們可以嘗試執行 可能 成功的作業,因此他們會將該作業包裝在區塊中 try/catch ,並在錯誤失敗時嘗試接受錯誤。

雖然此模式可能適用於用戶端應用程式,但是在執行外掛程式時,任何數據作業失敗都會導致復原整個交易。 您無法接受錯誤,因此您必須務必一律傳回 InvalidPluginExecutionException

錯誤「Sql 錯誤:執行逾時已過期」

錯誤碼: -2147204783
錯誤訊息:Sql 錯誤:「執行逾時已過期。 作業完成之前經過的逾時期間,或伺服器沒有回應。」

原因

發生 SQL 逾時錯誤的原因有很多種。 以下說明其中三個:

阻塞

SQL 逾時錯誤最常見的原因是作業正在等候其他 SQL 交易封鎖的資源。 此錯誤是 Dataverse 保護數據完整性,以及防止長時間執行的要求影響使用者效能的結果。

封鎖可能是因為其他並行作業所造成。 您的程式代碼在測試環境中可能會在隔離中正常運作,而且仍然容易受到只有在多個使用者在外掛程式中起始邏輯時才會發生的情況。

撰寫外掛程式時,請務必瞭解如何設計可調整的自定義。 如需詳細資訊,請 參閱 Dataverse 中的可調整自定義設計

串聯作業

您在外掛程式中所做的某些動作,例如指派或刪除記錄,可以起始相關記錄的串聯作業。 這些動作可能會對導致後續數據作業遭到封鎖的相關記錄套用鎖定,進而導致 SQL 逾時。

您應該考慮這些串聯作業對外掛程式中資料作業可能造成的影響。 如需詳細資訊,請參 閱數據表關聯性行為

由於這些行為可在環境之間以不同的方式設定,因此除非以相同方式設定環境,否則可能會難以重現行為。

新數據表上的索引

如果外掛程式使用最近建立的數據表或數據行來執行作業,則某些管理索引的 Azure SQL 功能可能會在數天后有所不同。

因用戶權力而導致的錯誤

在用戶端應用程式中,您可以停用不允許使用者執行的命令。 在外掛程式中,您沒有此功能。 您的程式代碼可能包含呼叫端用戶沒有執行許可權的一些自動化。

您可以將 [在使用者的內容中執行] 值設定為該使用者,以在已知具有正確許可權的用戶內容 註冊要執行的外掛程式。 或者,您可以模擬其他用戶來執行作業。 如需詳細資訊,請參閱:

在停用使用者的內容中執行時發生錯誤

當外掛程式在停用使用者的內容中執行時,會傳回下列錯誤:

錯誤訊息:System.ServiceModel.FaultException'1[Microsoft.Xrm.Sdk.OrganizationServiceFault]:在 OrganizationContext=<Context> 中具有 SystemUserId=<User-ID> 的使用者已停用。 停用的用戶無法存取系統。 請考慮啟用此使用者。 此外,如果未指派授權給使用者,則會停用使用者。

若要針對此錯誤進行疑難解答,您可以執行查詢來尋找已向停用用戶註冊的步驟,以及相關聯的外掛程式和 SdkMessage 詳細數據。

https://<env-url>/api/data/v9.2/sdkmessageprocessingsteps
?$filter=_impersonatinguserid_value eq '<disabled-userId-from-error>'&
$expand=plugintypeid($select=name,friendlyname,assemblyname;
$expand=pluginassemblyid($select=solutionid,name,isolationmode)),sdkmessageid($select=solutionid,name)&
$select=solutionid,name,stage,_impersonatinguserid_value,mode

錯誤「將內容傳送至沙盒時超過訊息大小」

錯誤碼: -2147220970
錯誤訊息:將內容傳送至沙盒時超過訊息大小。 訊息大小: ### Mb

當訊息承載大於 116.85 MB,且已註冊訊息的外掛程式時,就會發生此錯誤。 錯誤訊息包含造成此錯誤的承載大小。

此限制有助於確保執行應用程式的使用者不會根據資源條件約束互相干擾。 此限制有助於提供一層保護,以防止異常大型的訊息承載威脅 Dataverse 平臺的可用性和效能特性。

116.85 MB 夠大,因此很少會遇到這種情況。 這種情況最可能的情況是,當您擷取包含大型二進位檔之多個相關記錄的記錄時。

如果您收到此錯誤,您可以:

  1. 拿掉訊息的外掛程式。 如果沒有登錄訊息的外掛程式,作業就會完成,而不會發生錯誤。
  2. 如果錯誤發生在自定義用戶端中,您可以修改程式碼,使其不會嘗試在單一作業中執行工作。 相反地,請撰寫程式代碼來擷取較小組件中的數據。

錯誤「指定的索引鍵不存在於字典中」

Dataverse 經常使用衍生自抽象類的類別,該類別 DataCollection<TKey,TValue> 代表索引鍵和值的集合。 例如,使用外掛程式時, IExecutionContext屬性InputParametersParameterCollection 衍生自 類別的 DataCollection<TKey,TValue> 。 這些類別基本上是字典物件,您可以在其中使用索引鍵名稱存取特定值。

錯誤碼

當程式代碼中的索引鍵值不存在於集合中時,就會發生此錯誤。 結果是運行時錯誤,而不是平台錯誤。 當外掛程式內發生此錯誤時,錯誤碼取決於是否已攔截到錯誤。

如果開發人員攔截到例外狀況並傳回 InvalidPluginExecutionException,如 處理外掛程式中的例外狀況中所述,則會傳回下列錯誤:

錯誤碼: -2147220891
錯誤訊息:ISV 程式代碼中止作業。

不過,發生此錯誤時,開發人員通常無法正確攔截它,並傳回下列錯誤:

錯誤碼: -2147220956
錯誤訊息:ISV 程式代碼發生非預期的錯誤。

注意事項

“ISV” 代表 獨立軟體廠商

原因

此錯誤經常在設計時間發生,可能是因為拼字錯誤或使用不正確的大小寫。 索引鍵值會區分大小寫。

在運行時間,錯誤通常是因為開發人員假設值不存在時存在。 例如,在註冊更新數據表的外掛程式中,集合中只會包含已變更的EntityAttributes值。

解決方案

若要解決此錯誤,您必須先檢查密鑰是否存在,再嘗試使用它來存取值。

例如,存取數據表數據行時,您可以使用 Entity.Contains(String) 方法來檢查數據表中是否存在數據行,如下列程式代碼所示。

// Obtain the execution context from the service provider.  
IPluginExecutionContext context = (IPluginExecutionContext)
    serviceProvider.GetService(typeof(IPluginExecutionContext));

// The InputParameters collection contains all the data passed in the message request.  
if (context.InputParameters.Contains("Target") &&
    context.InputParameters["Target"] is Entity)
    {
    // Obtain the target entity from the input parameters.  
    Entity entity = (Entity)context.InputParameters["Target"];

    //Check whether the name attribute exists.
    if(entity.Contains("name"))
    {
        string name = entity["name"];
    }

有些開發人員會使用 Entity.GetAttributeValue<T>(String) 方法,以避免在存取數據表數據行時發生此錯誤。 如果數據行不存在,這個方法會傳回型別的預設值。 如果預設值為 null,這個方法會如預期般運作。 但是,如果預設值不會傳回 Null,例如搭配 DateTime,則傳回的值會是 1/1/0001 00:00 ,而不是 Null。

錯誤「您無法以與目前交易上已設定的隔離等級不同的隔離等級來啟動交易」

錯誤碼: -2147220989
錯誤訊息:您無法啟動隔離等級與目前交易中已設定不同的交易

外掛程式旨在支援商業規則。 不支援在同步外掛程式內修改數據架構的任何部分。 這些作業通常需要較長的時間,而且可能會導致應用程式使用的快取元數據變得不同步。不過,這些作業可以在註冊為以異步方式執行的外掛程式步驟中執行。

已知問題:Activity.RegardingObjectId 未使用外掛程式設定的名稱值

此問題最常見的徵兆是活動記錄中的 [ 關於 ] 字段會顯示 (No Name) ,而不是主要名稱屬性值。

在外掛程式內,您可以使用 EntityReference 值來設定查閱屬性。 不需要 EntityReference.Name 屬性。 一般而言,設定查閱屬性值時不需要包含它,因為 Dataverse 會設定它。 您應該在事件管線的 PreOperation 階段設定如下的值。 如需詳細資訊,請 參閱事件執行管線

此規則的例外狀況是設定 ActivityPointer.RegardingObjectId 查閱時。 衍生自 ActivityPointer 的所有實體類型都會繼承此查閱。 根據預設,這些包括 AppointmentChatEmailFaxLetterPhoneCallRecurringAppointmentMaster,以及任何建立為活動類型的自定義數據表。 如需詳細資訊,請參閱 活動數據表

如果您在 PreOperation 階段中設定此值,Dataverse 不會新增名稱值。 值為 Null,而且當您擷取記錄時,應該包含此值的格式化值不存在。

因應措施

有兩種方式可以解決此問題:

  1. 您可以 在設定 查閱屬性的值之前,使用正確的主要名稱域值來設定 EntityReference.Name 屬性值。
  2. 您可以在 PreValidation 階段中設定查閱值,而不是 PreOperation 階段。

其他相關資訊