这是我的第505篇原创文章,写于2023年11月25日。
项目中可能会碰到Flow (Power Automate) 看起来没有被触发,但是偶尔又能触发的样子。这时候请检查下系统作业表(asyncoperation)是否记录太多。
至于查看这个实体的元数据信息可以通过类似 https://luoyongdemo.crm.dynamics.cn/api/data/v9.2/EntityDefinitions(LogicalName='asyncoperation') 的URL来查看,因为这个表在默认解决方案中也看不到。如果要看所有列的信息可以通过 https://luoyongdemo.crm.dynamics.cn/api/data/v9.2/EntityDefinitions(LogicalName='asyncoperation')/Attributes 的URL来查看。如果要看某个具体列的信息则可以通过 https://luoyongdemo.crm.dynamics.cn/api/data/v9.2/EntityDefinitions(LogicalName='asyncoperation')/Attributes(LogicalName='statecode') 的URL来查看。
重要的列就是statecode和statuscode,但是通过
https://luoyongdemo.crm.dynamics.cn/api/data/v9.2/EntityDefinitions(LogicalName='asyncoperation')/Attributes(LogicalName='statuscode')/Microsoft.Dynamics.CRM.PicklistAttributeMetadata?$select=LogicalName&$expand=OptionSet($select=Options),GlobalOptionSet($select=Options)
这样的URL查不到值列表。却可以通过类似
https://luoyongdemo.crm.dynamics.cn/api/data/v9.2/stringmaps?$select=attributevalue,value,langid&$filter=objecttypecode eq 'asyncoperation' and attributename eq 'statuscode' and langid eq 2052
这样的URL看到。
我这里讲值列出来如下:
表名 | 字段名 | 存储值 | 显示值 |
asyncoperation | statecode | 0 | 准备就绪 |
asyncoperation | statecode | 1 | 暂停 |
asyncoperation | statecode | 2 | 已锁定 |
asyncoperation | statecode | 3 | 已完成 |
asyncoperation | statuscode | 0 | 正在等待资源 |
asyncoperation | statuscode | 10 | 等待中 |
asyncoperation | statuscode | 20 | 正在进行 |
asyncoperation | statuscode | 21 | 正在暂停 |
asyncoperation | statuscode | 22 | 正在取消 |
asyncoperation | statuscode | 30 | 成功 |
asyncoperation | statuscode | 31 | 失败 |
asyncoperation | statuscode | 32 | 已取消 |
如果要看这个表有多少条记录呢?根据 Query data using the Web API 的说法,如果表中的记录不超过5万行的话,可以用类似
https://luoyongdemo.crm.dynamics.cn/api/data/v9.2/asyncoperations?$apply=aggregate($count as count)
这样的语句查看。如果要看不同状态statuscode下记录数的汇总的话可以通过类似
https://luoyongdemo.crm.dynamics.cn/api/data/v9.2/asyncoperations?$apply=groupby((statuscode),aggregate($count as count))
这样的语句查看。
如果超过5万行报错的话,还可以通过 RetrieveTotalRecordCount Function 来看,但是这个不是很准,是过去24小时的快照,示例如下:
https://luoyongdemo.crm.dynamics.cn/api/data/v9.2/RetrieveTotalRecordCount(EntityNames=['asyncoperation'])
如果statuscode < 30的记录太多,那就可能是异步服务队列积压了,这时候怎么办?清理呗。有些系统作业或许可以取消,比如说程序bug导致了大量误触发,或者某些系统标准的异步插件(见下图是一个典型的与linkin相关的但是我们中国大陆版本不需要的功能)被触发了很多次等,这时候可以考虑取消还没有运行的但是没有用的系统作业。
最好是找准取消哪些系统作业,可以找一些出来看看,比如我看到某个很多系统作业等待运行的很多就取消这个,我一般通过XrmToolBox 中的 SQL 4 CDS 工具来进行处理,类似SQL如下:
这里有个技巧就是要先处理最近产生的记录,也就是createdon字段比较大的。不然的话执行可能会报错,一次处理不了多少。当然可以不断的处理,一次处理的记录不要超过10万条。
update asyncoperation set statecode=3,statuscode=32
where owningextensionid='045e1e42-bdd1-4b4f-b3c5-7bbc0f724ee7' and statecode in (0,1,2)
and createdon> '2023-11-16 07:00:00.000' and createdon<'2023-11-16 08:30:00.000'
用SQL处理起来快,但是如果要用代码呢,可以使用类似如下的FetchXml执行分页查询,
<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>
<entity name='asyncoperation'>
<attribute name='asyncoperationid' />
<attribute name='name' />
<attribute name='statuscode' />
<attribute name='statecode' />
<order attribute='startedon' descending='true' />
<filter type='and'>
<condition attribute='name' operator='eq' value='{作业名称}' />
<condition attribute='statecode' operator='in'>
<value>0</value>
<value>1</value>
<value>2</value>
</condition>
</filter>
</entity>
</fetch>
然后将查找出来的系统作业取消,类似下面的代码:
using Microsoft.Xrm.Sdk;
using System;
foreach (var entity in lstEntity)
{
Entity systemJob = new Entity("asyncoperation", entity.Id);
systemJob["statuscode"] = new OptionSetValue(32);
systemJob["statecode"] = new OptionSetValue(3);
try
{
orgService.Update(systemJob);
}
catch (Exception ex)
{
Console.WriteLine(string.Format("取消作业 {0} 失败! {ex.message}", entity.Attributes.FirstOrDefault(attr => attr.Key == "name").Value));
}
}
当然逐条处理太慢,可以批量处理,请参考我的文章:Dynamics 365使用Execute Multiple Request删除系统作业实体记录 。
如果不是要取消指定的系统作业而是全部取消,还有别的办法,就是将进入Power Platform Admin Center将这个环境(environment)的Aministrator mode打开,Background operations保持为Disabled状态。过一阵子所有的异步系统作业就会被取消了,取消完成了再恢复成正常模式就可以了。
我还有些其他文章可以参考用于解决排查类似问题如下: