Dataverse 插件疑难解答

本文包含有关插件执行期间可能发生的错误的信息,或与插件相关的 Dataverse 错误,以及如何避免或修复这些错误。

错误“无法完成时间转换”

错误代码:-2147220956
错误消息:无法完成转换,因为提供的 DataTime 未正确设置 Kind 属性。 例如,当 Kind 属性为 DateTimeKind.Local 时,源时区必须为 TimeZoneInfo.Local。

在插件代码中的调用期间 TimeZoneInfo.ConvertTimeToUtc(DateTime, TimeZoneInfo) ,可能会发生此错误,以将圣地亚哥或伏尔戈格勒时区中的值转换为 DateTime 协调世界时(UTC)。

此错误是由已知的产品限制引起的,目前没有解决方法。

有关详细信息,请参阅 为用户指定时区设置。

错误“沙盒工作进程崩溃”

错误代码:-2147204723
错误消息:插件执行失败,因为沙盒工作进程崩溃。 这通常是由于插件代码中的错误造成的。

此错误只是意味着运行插件代码的工作进程崩溃。 插件可能是崩溃的原因,但它也可能是组织并发运行的另一个插件。 由于进程崩溃,因此无法提取有关它崩溃的原因的任何更具体的信息。 但在检查故障转储的数据后,我们发现此错误通常是由于以下四个原因之一导致的:

插件中未经处理的异常

编写插件时,应尝试预测哪些操作可能会失败,并将其放在 try-catch 块中。 在发生错误时,应使用 InvalidPluginExecutionException 类以对用户有意义的错误信息以合理的方式终止操作。

有关详细信息,请参阅 处理插件中的异常。

此异常的常见方案是在使用 HttpClient.SendAsyncHttpClient.GetAsync 方法时。 这些 HttpClient 方法是返回 任务的异步操作。 若要在代码需要同步的插件中工作,用户可以使用 Task<TResult>。Result 属性。 发生错误时, Result 返回 AggregateException。 将 AggregateException 多个故障合并到单个异常中,这可能难以处理。 更好的设计是使用 Task<TResult>.GetAwaiter().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. 在“应用洞察”页面上,选择左侧面板中的失败
  5. “失败”页上,选择“异常”。
  6. “异常问题 ID”下,在 “总体列表中选择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"
    }
}

下面显示了如何在插件 Tracelog 中记录此错误:

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/块中,并尝试在失败时忽略错误。

虽然此模式可能适用于客户端应用程序,但在插件执行过程中,任何数据操作失败都会导致回滚整个事务。 不能忽视错误,因此必须确保始终返回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.属性是从InputParameters类派生的ParameterCollectionDataCollection<TKey,TValue>。 这些类本质上是使用键名称访问特定值的字典对象。

错误代码

当代码中的键值在集合中不存在时,会发生此错误。 结果是运行时错误,而不是平台错误。 在插件中发生此错误时,错误代码取决于是否捕获了错误。

如果开发人员捕获了异常并返回InvalidPluginExecutionException,如插件中的 Handle 异常中所述,将返回以下错误:

错误代码:-2147220891
错误消息:ISV 代码中止了操作。

但是,由于此错误,开发人员通常无法正确捕获此错误,并返回以下错误:

错误代码:-2147220956
错误消息:ISV 代码中出现意外错误。

注意

“ISV”代表 独立软件供应商

原因

此错误经常在设计时发生,可能是由于拼写错误或使用不正确的大小写导致的。 键值区分大小写。

在运行时,错误通常是由于开发人员假设值存在而实际上不存在。 例如,在为表的更新注册的插件中,只有更改的那些值被包含在Entity集合Attributes中。

解决方法

若要解决此错误,必须先检查密钥是否存在,然后再尝试使用它来访问值。

例如,访问表列时,可以使用 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 阶段设置查找值。

详细信息