我是微軟Dynamics 365 & Power Platform方面的工程師/顧問羅勇,也是2015年7月到2018年6月連續三年Dynamics CRM/Business Solutions方面的微軟最有價值專家(Microsoft MVP),歡迎關注我的微信公衆号 MSFTDynamics365erLuoYong ,回複462或者20220131可友善擷取本文,同時可以在第一間得到我釋出的最新博文資訊,follow me!
我們知道插件或者自定義工作流活動,現在新推出的Custom API都受到要在兩分鐘之内運作完畢的限制,且該限制無法更改。是以如果處理很多記錄的時候要切割開來處理,否則可能碰到在開發環境因為資料量少沒問題,到了生産環境資料量大不能在2分鐘内處理完畢就會有問題。今天我來介紹下用Flow調用Custom API逐頁處理資料的一種方法。
因為我前面的博文 Dynamics 365的Custom API介紹 對Custom API介紹的比較詳細,是以我這裡不會詳細說如何建立Custom API,就指出一些需要注意的地方和參數。Custom API的Is Fuction記得要設定為No,因為據我所知,調用Function類型的Custom API沒有那麼簡便,當然啦,我們這裡是處理資料,也不應該用Function這種類型。
然後我新增了分頁需要的三個輸入參數如下:
也有一個輸出參數如下:
然後Custom API我使用的代碼如下:
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Xml.Linq;
namespace D365.Plugins
{
public class CustomAPIHandleDataPagebyPage : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
//擷取日志服務
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
//寫一些日志,友善跟蹤
tracingService.Trace($"Enter CustomAPIHandleDataPagebyPage on {DateTime.UtcNow.ToString()}");
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService adminOrgSvc = serviceFactory.CreateOrganizationService(null);
string pagingCookie = context.InputParameters["ly_pagingCookie"].ToString();
int pageNumber = Convert.ToInt32(context.InputParameters["ly_pageNumber"].ToString());
int recordsPerPage = Convert.ToInt32(context.InputParameters["ly_recordsPerPage"].ToString());
tracingService.Trace($"pagingCookie={pagingCookie},pageNumber={pageNumber},recordsPerPage={recordsPerPage}");
string nextPageCookie = string.Empty;
string fetchXml = @"<fetch version='1.0' mapping='logical' distinct='false'>
<entity name='ly_demosubentity'>
<attribute name='ly_demosubentityid' />
<attribute name='ly_decimalfield2' />
<order attribute='ly_demosubentityid' descending='false' />
<filter type='and'>
<condition attribute='statecode' operator='eq' value='0' />
</filter>
</entity>=
</fetch>";
string xml = CreateXml(fetchXml, pagingCookie, pageNumber, recordsPerPage);
tracingService.Trace($"xml={xml}");
RetrieveMultipleRequest retrieveRequest = new RetrieveMultipleRequest
{
Query = new FetchExpression(xml)
};
retrieveRequest.Parameters.Add("BypassCustomPluginExecution", true);
EntityCollection entityCollection = ((RetrieveMultipleResponse)adminOrgSvc.Execute(retrieveRequest)).EntityCollection;
if (entityCollection.MoreRecords)
{
nextPageCookie = entityCollection.PagingCookie;
}
foreach (var entity in entityCollection.Entities)
{
entity["ly_decimalfield2"] = (decimal)2022;
adminOrgSvc.Update(entity);
}
context.OutputParameters["ly_nextPageCookie"] = nextPageCookie;
}
public string CreateXml(string xml, string cookie, int page, int count)
{
XDocument doc = XDocument.Parse(xml);
if (!string.IsNullOrEmpty(cookie))
{
doc.Root.Add(new XAttribute("paging-cookie", cookie));
}
doc.Root.Add(new XAttribute("page", page));
doc.Root.Add(new XAttribute("count", count));
return doc.ToString(SaveOptions.DisableFormatting);
}
}
}
然後我建立一個Flow來測試下:
Flow中我先聲明兩個變量如下:
因為要循環處理,是以這裡我添加了一個Do Until,外層設定如下:
判斷表達式左邊用的是 empty(variables('PagingCookie')) 。
Do Until調用Microsoft Dataverse連接配接器的 Perform an unbound action,設定如下:
然後還要将Custom API傳出的輸出參數設定下,如下:
還有頁碼要增加1,設定如下:
總體如下: