[本文是预发行文档,可能会有所更改。]
使用后台操作来发送由 Dataverse 异步处理的请求。 如果您不想在请求运行时保持连接,后台操作非常有用。
后台操作完成后,您可以通过以下两种方式之一收到通知:
可以通过以下两种方式之一检索后台操作的结果:
若要在后台运行请求,请将该操作定义为自定义 API。 有关详细信息,请参阅 创建和使用自定义 API 并 检索有关自定义 API 的数据。
自定义 API 使用插件来执行数据操作。 与所有 Dataverse 插件一样,这些插件的执行超时为两分钟。 异步发送请求不提供更多的执行时间。
所需权限
若要执行后台操作,发起操作的用户必须具有对 backgroundoperations 表中读取和写入的访问权限。 将 prvReadbackgroundoperation 和 prvWritebackgroundoperation 权限分配给用户以授予此访问权限。
- SDK: AddPrivilegesRoleRequest
- Web API:AddPrivilegesRole 操作
请求异步处理
可以使用 SDK for .NET 或 Dataverse Web API 在后台运行异步请求。
本文中的示例使用名为 sample_ExportDataUsingFetchXmlToAnnotation 的自定义 API。 有关此自定义 API 的详细信息,请参阅 示例:ExportDataUsingFetchXmlToAnnotation 自定义 API。
使用 ExecuteBackgroundOperation 消息。
SDK 没有 ExecuteBackgroundOperation 请求和响应类。 在添加这些类之前,请按照 使用 .NET SDK 进行消息处理 中的描述,使用基本 OrganizationRequest 和 OrganizationResponse 类。
下表描述了消息的 ExecuteBackgroundOperation 输入参数。
| Name | 类型 | Description |
|---|---|---|
Request |
OrganizationRequest | (必需)包含要异步处理的请求。 请求的 Dataverse 消息必须作为自定义 API 实现。 |
CallbackUri |
字符串 | (可选)Dataverse 在作完成后向此 URL 发送 POST HTTP 请求。 |
下表描述了消息的 ExecuteBackgroundOperation 输出参数。
| Name | 类型 | Description |
|---|---|---|
BackgroundOperationId |
Guid | 标识您可用于监视或取消请求处理的背景操作表行。 |
Location |
字符串 | 标识您可用于检索请求状态或取消请求的状态监视器资源 URL。 |
以下静态方法使用 ExecuteBackgroundOperation 和 sample_ExportDataUsingFetchXmlToAnnotation 自定义 API。
static void SendRequestAsynchronously(IOrganizationService service)
{
//Create a request for message defined as a custom API to run in the background
var asyncRequest = new OrganizationRequest("sample_ExportDataUsingFetchXmlToAnnotation")
{
Parameters =
{
{"FetchXml", @"<fetch>
<entity name='account'>
<attribute name='accountid'/>
<attribute name='name'/>
</entity>
</fetch>" }
}
};
//Create a request to execute the message in the background
var request = new OrganizationRequest("ExecuteBackgroundOperation")
{
Parameters =
{
{"Request", asyncRequest }
}
};
//Execute the background operation request
var response = service.Execute(request);
Console.WriteLine($"BackgroundOperationId: {response["BackgroundOperationId"]}");
Console.WriteLine($"Location: {response["Location"]}");
}
输出:
BackgroundOperationId: <backgroundoperationid value>
Location: [Organization URI]/api/backgroundoperation/<backgroundoperationid value>
详细了解 IOrganizationService 接口 以及如何 将消息与 SDK for .NET 配合使用。
管理后台操作
当您发送后台处理请求时,响应结果包含两个值,这些值表示可用于监视或取消后台操作的不同方法。
使用表中行
backgroundoperations的 ID 检索或更新表中的数据:使用表示状态监控资源的
LocationURL来轮询和取消后台操作。重要
状态监视器资源不是 Web API
backgroundoperationEntityType 资源。URL Example 状态监视器资源 [Organization URI]/api/backgroundoperation/<backgroundoperationid value>backgroundoperationEntityType 资源[Organization URI]/api/data/v9.2/backgroundoperations(<backgroundoperationid value>)状态监视器资源不是 Dataverse Web API 的一部分。 请注意,URL 不包含
/data/v9.2/。 状态监视器资源仅支持 GET 和 DELETE 操作,其行为与 Web APIbackgroundoperationEntityType 资源不相同。
查询后台作表或状态监视器资源以检查请求通常称为 状态轮询。 避免过度轮询,因为它可能会对性能产生负面影响。 如果需要,请每隔一分钟或多分钟轮询。
后台操作表
背景操作表包含有关异步处理请求的信息。 此表具有逻辑名称 backgroundoperation 和实体集名称 backgroundoperations。
了解后台操作实体类型 (backgroundoperation EntityType)。
下表描述了可用于管理后台作业状态的列。
| 显示名称 架构名称 逻辑名称 |
类型 | Description |
|---|---|---|
后台操作BackgroundOperationIdbackgroundoperationid |
唯一标识符 | 主键 |
状态StateCodebackgroundoperationstatecode |
选择列表 | 后台操作的状态 选项: - 值: 0,标签: 就绪- 值: 2,标签: 已锁定- 值: 3,标签: 已完成 |
状态描述StatusCodebackgroundoperationstatuscode |
选择列表 | 后台操作的状态 选项: - 值: 0,标签: 等待资源 (状态:就绪)- 值: 20,标签: 正在进行 (状态:已锁定)- 值: 22,标签: 取消 (状态:已锁定)- 值: 30,标签: 成功 (状态:已完成)- 值: 31,标签: 失败 (状态:已完成)- 值: 32,标签: 已取消 (状态:已完成) |
NameNamename |
String |
UniqueName用于后台操作的定制 API |
显示名称DisplayNamedisplayname |
String |
DisplayName用于后台操作的自定义 API |
输入参数InputParametersinputparameters |
备忘录 | 用于启动后台操作的输入参数 此字符串是一个包含 Key 和 Value 的 JSON 序列化数组。 |
输出参数OutputParametersoutputparameters |
备忘录 | 后台操作的响应 此字符串是 Key 和 Value 组成的 JSON 序列化数组。 |
开始时间StartTimestarttime |
日期时间 | 后台操作开始执行时 |
结束时间EndTimeendtime |
日期时间 | 后台操作执行完毕后 |
重试计数RetryCountretrycount |
整数 | 重试后台操作的次数 |
错误代码ErrorCodeerrorcode |
整数 | 如果后台操作失败,错误代码 如果错误来自 Dataverse,则它具有一个整数值,该值对应于 Web 服务错误代码中列出的代码之一。 如果错误不是来自 Dataverse,则该值设置为零。 |
错误消息ErrorMessageerrormessage |
备忘录 | 如果后台操作失败,错误信息 |
运行方式RunAsrunas |
String | 用于执行后台操作的systemusersystemuserid |
创建日期CreatedOncreatedon |
日期时间 | 创建记录时 |
生存时间TTLInSecondsttlinseconds |
整数 | 生存时间(以秒为单位),之后会自动删除记录;默认值为 90 天 |
轮询后台操作表
请确保在查询中包含这些列:
namebackgroundoperationstatecodebackgroundoperationstatuscodeoutputparameterserrorcodeerrormessage
轮询表的方式取决于使用的是 SDK 还是 Web API。
static void PollBackgroundOperationRequest(IOrganizationService service, Guid backgroundOperationId)
{
// List of columns that will help to get status, output and error details if any
var columnSet = new ColumnSet(
"name",
"backgroundoperationstatecode",
"backgroundoperationstatuscode",
"outputparameters",
"errorcode",
"errormessage");
try
{
// Get the entity with all the required columns
var backgroundOperation = service.Retrieve("backgroundoperation", backgroundOperationId, columnSet);
Console.WriteLine($"Name: {backgroundOperation["name"]}");
Console.WriteLine($"State Code: {backgroundOperation.FormattedValues["backgroundoperationstatecode"]}");
Console.WriteLine($"Status Code: {backgroundOperation.FormattedValues["backgroundoperationstatuscode"]}");
Console.WriteLine($"Output Parameters:");
// Deserialize the Output Parameters into KeyValuePair<string, string>
List<KeyValuePair<string, string>>? output =
System.Text.Json.JsonSerializer
.Deserialize<List<KeyValuePair<string, string>>>((string)backgroundOperation["outputparameters"]);
output.ForEach(x => {
Console.WriteLine($"\t{x.Key}: {x.Value}");
});
Console.WriteLine($"Error Code: {backgroundOperation.GetAttributeValue<string>("errorcode")}");
Console.WriteLine($"Error Message: {backgroundOperation.GetAttributeValue<string>("errormessage")}");
}
// Catch Dataverse errors
catch (FaultException<OrganizationServiceFault> ex)
{
Console.WriteLine($"ErrorCode:{ex.Detail.ErrorCode}");
Console.WriteLine($"Message:{ex.Detail.Message}");
}
// Catch other errors
catch (Exception error)
{
Console.WriteLine($"Some other error occurred: '{error.Message}'");
}
}
等待输出:
Name: sample_ExportDataUsingFetchXmlToAnnotation
State Code: Locked
Status Code: In Progress
Output Parameters:
Error Code:
Error Message:
完成输出:
Name: sample_ExportDataUsingFetchXmlToAnnotation
State Code: Completed
Status Code: Succeeded
Output Parameters:
AnnotationId: {value}
Error Code:
Error Message:
错误输出:
Name: sample_ExportDataUsingFetchXmlToAnnotation
State Code: Completed
Status Code: Failed
Output Parameters:
Error Code: -2147187707
Error Message: Access is denied.
如果平台生成错误,则它具有一个整数值,该值对应于 Web 服务错误代码中列出的代码之一。 如果平台不生成错误,请将其值设置为零。
找不到 ID:
ErrorCode:-2147185406
Message:The HTTP status code of the response was not expected (404).
Status: 404
Response:
{"error":{"message":"Could not find item '110eaa68-db17-4115-ad74-d185823fc089'.","details":[{"message":"\r\nErrors : [\r\n \"Resource Not Found. Learn more: https://aka.ms/cosmosdb-tsg-not-found\"\r\n]\r\n"}]}}
轮询状态监视器资源
可以使用 GET 请求轮询状态监视器资源。 此请求返回后台操作的状态。 如果操作已完成,则提供自定义 API 的输出。 如果在执行过程中发生错误,则会收到错误消息和代码。
将请求发送到原始请求在Location响应标头中返回的状态监视器资源 URL。
请求:
GET [Organization URI]/api/backgroundoperation/{backgroundoperationid}
Content-Type: application/json
响应:
HTTP/1.1 200 OK
Content-Type: application/json
{
backgroundOperationErrorCode: {INT},
backgroundOperationErrorMessage: {string},
backgroundOperationStateCode: {INT},
backgroundOperationStatusCode: {INT},
outputParam1: {value},
outputParam2: {value},
outputParam3: {value},
}
仅当发生错误时,响应才包括 backgroundOperationErrorCode 和 backgroundOperationErrorMessage 值。 仅当操作成功完成时,它才包括输出参数。
状态监视器资源不提供标签。
接收结果通知
若要在后台操作完成时获取通知,可以 包含请求的回调 URL 或 订阅 OnBackgroundOperationComplete 事件。
请求电话回拨
可以在请求中指定 URL,以在作完成后接收回调。 Dataverse 使用此 URL 发送具有以下有效负载的 POST 请求:
{
"location": "< status monitor resource URL >",
"backgroundOperationId": "{GUID}",
"backgroundOperationStateCode": {INT},
"backgroundOperationStatusCode": {INT},
"backgroundOperationErrorCode": {INT},
"backgroundOperationErrorMessage": {string},
}
backgroundOperationErrorCode 并且 backgroundOperationErrorMessage 仅在发生错误时包含。
回调有效负载不包含任何输出参数。 接收回调的站点必须使用状态监视器资源 URL 发送经过身份验证的 GET 请求才能获取结果。
如果 URL 需要身份验证,则必须是自给自足 的共享访问签名 (SAS) URL。 不能再包含任何用来提供 API 密钥或令牌进行身份验证的标头。
若要测试回调 URL,请考虑使用 类似于 webhook.site 的网站。
请求回调的方式取决于使用的是 SDK 还是 Web API。 以下示例通过使用 webhook 向 webhook.site 发送请求以进行测试。
通过使用 SDK,将 ExecuteBackgroundOperation.CallbackUri 参数设置为 URL 以发送请求。
static void SendRequestAsynchronouslyWithCallback(IOrganizationService service)
{
//Create a request for message defined as a custom API to run in the background
var asyncRequest = new OrganizationRequest("sample_ExportDataUsingFetchXmlToAnnotation")
{
Parameters =
{
{"FetchXml", @"<fetch>
<entity name='account'>
<attribute name='accountid'/>
<attribute name='name'/>
</entity>
</fetch>" }
}
};
//Create a request to execute the message in the background
var request = new OrganizationRequest("ExecuteBackgroundOperation")
{
Parameters =
{
{"Request", asyncRequest },
// Request a callback
{"CallbackUri", "https://webhook.site/<id>" }
}
};
//Execute the background operation request
var response = service.Execute(request);
Console.WriteLine($"BackgroundOperationId: {response["BackgroundOperationId"]}");
Console.WriteLine($"Location: {response["Location"]}");
}
订阅 OnBackgroundOperationComplete 事件
在 OnBackgroundOperationComplete 消息上注册一个步骤,可以在后台操作完成时收到通知。 此消息是仅支持异步步骤注册的自定义 API。 它是使用自定义 API 来表示 业务事件的消息类型的示例。
顾名思义,每当后台操作完成时,都会触发 OnBackgroundOperationComplete 事件。 在此事件上注册异步步骤时,可以在插件中执行任何类型的逻辑,或将数据转发到 Azure 服务或 Webhook。 有关详细信息,请参见:
下表描述了消息的 OnBackgroundOperationComplete 输入和输出参数。
输入参数:
| Name | 类型 | Description |
|---|---|---|
PayloadType |
整数 | 后台操作完成时发送到回调 URI 的响应类型。 后台操作始终为零。 此字段是内部字段,不应更新。 |
LocationUrl |
String | 位置 URL |
BackgroundOperationId |
Guid | 后台操作的 ID |
输出参数:
| Name | 类型 | Description |
|---|---|---|
OperationName |
String | 操作名称 |
BackgroundOperationStateCode |
整数 | 后台操作状态代码 |
BackgroundOperationStatusCode |
整数 | 后台操作状态代码 |
配置 OnBackgroundOperationComplete 消息,如说明中所示,以 注册插件。 将消息名称设置为 OnBackgroundOperationComplete. 将 Auto Delete 设置为 true,以便自动删除 系统作业(AsyncOperation) 记录。
取消后台操作
如果您发起的后台操作尚未启动,可以取消。
- 如果操作没有启动,Dataverse 不会执行该操作。
- 如果操作已启动,Dataverse 不会停止该操作。
- 如果在执行取消的后台作期间发生错误,Dataverse 不会重试。
- 如果操作已经完成,则会出现以下错误:
Canceling background operation is not allowed after it is in terminal state.
可以通过以下两种方式之一取消后台操作:
通过更新 backgroundoperations 来取消后台操作
更新表中的 backgroundoperations 行,将设置为 backgroundoperationstatecode2 “已锁定”和 backgroundoperationstatuscode22 “取消”。
更新 backgroundoperations 表的方式取决于使用的是 SDK 还是 Web API。
static void CancelBackgroundOperationRequest(
IOrganizationService service,
Guid backgroundOperationId)
{
var backgroundOperation = new Entity(
entityName: "backgroundoperation",
id: backgroundOperationId)
{
Attributes =
{
//Set state as Locked
{"backgroundoperationstatecode", new OptionSetValue(2) },
//Set status as Cancelling
{"backgroundoperationstatuscode", new OptionSetValue(22) }
}
};
service.Update(backgroundOperation);
}
将 DELETE 请求发送到状态监视器资源
您还可以通过向状态监视器资源发送 DELETE 请求来取消后台操作。
请求:
DELETE [Organization URI]/api/backgroundoperation/{backgroundoperationid}
响应:
HTTP/1.1 200 Ok
{
backgroundOperationStateCode: 2,
backgroundOperationStatusCode: 22
}
重试
如果在执行请求期间发生错误,则系统最多重试三次。 这些重试使用 指数退避策略。