排查 Dataverse 插件问题
本文包含有关插件执行期间可能发生的错误或与插件相关的 Dataverse 错误以及如何避免或修复这些错误的信息。
错误“无法完成时间转换”
错误代码: -2147220956
错误消息:无法完成转换,因为提供的 DataTime 未正确设置 Kind 属性。 例如,当 Kind 属性为 DateTimeKind.Local 时,源时区必须为 TimeZoneInfo.Local。
在调用插件代码以将圣地亚哥或伏尔加格勒时区的值转换为DateTime
协调世界时 (UTC) 时TimeZoneInfo.ConvertTimeToUtc(DateTime, TimeZoneInfo),可能会出现此错误。
此错误是由已知的产品限制引起的,目前没有解决方法。
有关详细信息,请参阅 为用户指定时区设置。
错误“沙盒工作进程崩溃”
错误代码: -2147204723
错误消息:插件执行失败,因为沙盒工作进程崩溃。 这通常是由插件代码中的错误导致的。
此错误仅表示运行插件代码的工作进程崩溃。 插件可能是崩溃的原因,但它也可能是组织并发运行的另一个插件。 由于进程崩溃,因此无法提取有关崩溃原因的任何更具体的信息。 但在检查故障转储后的数据后,我们发现此错误通常由以下四个原因之一导致:
插件中未经处理的异常
编写插件时,应尝试预测哪些操作可能会失败,并将其包装在 try-catch 块中。 发生错误时,应使用 InvalidPluginExecutionException 类以对用户有意义的错误正常终止操作。
有关详细信息,请参阅 处理插件中的异常。
此异常的常见方案是使用 HttpClient.SendAsync 或 HttpClient.GetAsync 方法。 这些 HttpClient 方法是返回 Task 的异步操作。 若要在代码需要同步的插件中工作,可以使用 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 链接到环境。
- 等待,直到插件异常导致工作进程的崩溃错误。
- 在 Power Platform 管理中心中,导航到 Application Insights。
- 在“Application Insights”页上,选择左侧面板中的“ 失败 ”。
- 在 “失败 ”页上,选择“ 异常”。
- 在 “异常问题 ID”下的“ 总体 ”列表中,选择“ Microsoft.PowerPlatform.Dataverse.Plugin.PluginWorkerCrashException”。
- 在页面右侧的 “整体”下,选择“ PluginWorkerCrashException”。 现在,你将看到所有记录的工作进程崩溃异常的详细信息。
- 在左侧面板中搜索并选择所需的异常,异常详细信息报告将显示在页面的右侧, (查看前面的屏幕截图,了解示例) 。
- 若要访问堆栈跟踪,请在报表中展开 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& 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: #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& wcfExecInMs, Int64& initializeInMs, Int64& trackCallInMs, Int64& trackGoodReturnInMs, Int64& waitInMs, Int64& taskStartDelay)</OriginalException>
<TraceText i:nil="true" />
</OrganizationServiceFault>
工作进程达到内存限制
每个工作进程都具有有限的内存量。 在某些情况下,包含大量数据的多个并发操作可能会超过可用内存,并导致进程辅助角色崩溃。
RetrieveMultiple with File data
在本例中,常见方案是为请求包含文件数据的操作执行 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 足够大,这种情况应该很少出现。 最有可能发生这种情况的情况是检索包含大型二进制文件的多个相关记录的记录。
如果收到此错误,可以:
- 删除消息的插件。 如果没有为消息注册插件,则操作完成而不会出错。
- 如果错误发生在自定义客户端中,则可以修改代码,使其不会尝试在单个操作中执行工作。 相反,请编写代码以检索较小部分的数据。
错误“字典中不存在给定键”
Dataverse 经常使用派生自抽象 DataCollection<TKey,TValue> 类的类,这些类表示键和值的集合。 例如,对于插件,IExecutionContext. 属性是从 ParameterCollection 类派生的DataCollection<TKey,TValue>InputParameters。 这些类本质上是字典对象,可在其中使用键名称访问特定值。
错误代码
当代码中的键值在集合中不存在时,会发生此错误。 结果是运行时错误,而不是平台错误。 当插件中发生此错误时,错误代码取决于是否已捕获错误。
如果开发人员捕获了异常并返回 了 InvalidPluginExecutionException,如 处理插件中的异常中所述,将返回以下错误:
错误代码: -2147220891
错误消息:ISV 代码中止了操作。
但是,对于此错误,开发人员通常无法正确捕获它,并返回以下错误:
错误代码: -2147220956
错误消息:ISV 代码出现意外错误。
注意
“ISV”代表 独立软件供应商。
原因
此错误经常在设计时发生,可能是由于拼写错误或使用大小写不正确。 键值区分大小写。
在运行时,错误通常是由于开发人员假设值不存在时存在。 例如,在为更新表注册的插件中,只有更改的值包含在 集合Attributes中Entity。
解决方案
若要解决此错误,必须先检查密钥存在,然后再尝试使用它来访问值。
例如,访问表列时,可以使用 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
的所有实体类型都继承此查找。 默认情况下,其中包括约会、聊天、Email、传真、信函、电话Call、RecurrenceingAppointmentMaster 以及创建为活动类型的任何自定义表。 有关详细信息,请参阅 活动表。
如果在 PreOperation 阶段设置此值,则 Dataverse 不会添加名称值。 该值为 null,并且检索记录时,应包含此值的格式化值不存在。
解决方法
可通过两种方法解决此问题:
- 在设置查找属性的值之前,可以使用正确的主名称字段值设置 EntityReference.Name 属性值。
- 可以在 PreValidation 阶段而不是 PreOperation 阶段中设置查找值。