我想构建一个控制台应用程序,它可以获取 xml 查询并使用 Microsoft.Xrm.Sdk 对所有结果启动工作流程。
我使用 FetchExpression 将 xml 字符串解释为查询,并使用 RetireveMultiple 来获取结果。
不幸的是 RetrieveMultiple 似乎页面大小限制为 5000。
我在其他项目中使用 QueryExpression 解决了这个问题,设置其 PagingInfo 并循环直到没有更多记录,但 FetchExpression 似乎没有此分页选项。
任何人都可以提出一个解决方案来解决这个问题吗?或者是否有另一种方法可以跨 1000 条记录运行工作流程,而无需在 UI 中对所有记录进行分页?
using System;
using System.Configuration;
using System.Linq;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Tooling.Connector;
class Program
{
static void Main(string[] args)
{
const string WORKFLOW_NAME = "Do the thing";
const string FETCH_XML_QUERY = @"<fetch version=""1.0"" output-format=""xml-
platform"" mapping=""logical"" distinct=""false"">
<entity name=""new_thing"">
<attribute name=""new_thingid"" />
<attribute name=""new_name"" />
<attribute name=""createdon"" />
<order attribute=""new_name"" descending=""false"" />
<filter type=""and"">
<condition attribute=""statecode"" operator=""eq"" value=""0"" />
</filter>
</entity>
</fetch>";
try
{
var ds = new CRM.CRMService().CreateService() as OrganizationServiceProxy;
using (var service = new CrmServiceClient(ds))
{
if (service.IsReady)
{
Console.WriteLine($"Connected to Dynamics 365: {ConfigurationManager.AppSettings["CRM.ServiceUrl"]}");
// Retrieve the workflow by name
var query = new QueryExpression("workflow");
query.ColumnSet.AddColumns("workflowid");
query.Criteria.AddCondition("name", ConditionOperator.Equal, WORKFLOW_NAME);
Entity workflowEntity = service.RetrieveMultiple(query).Entities.FirstOrDefault();
if (workflowEntity != null)
{
// Retrieve entities using FetchXML query
EntityCollection entityCollection = service.RetrieveMultiple(new FetchExpression(FETCH_XML_QUERY));
Console.WriteLine($"Retrieved {entityCollection.Entities.Count} entities.");
Console.WriteLine($"Run workflow: \"{WORKFLOW_NAME}\" ? Y or N");
var key = Console.ReadLine();
if (key.ToLower() == "y")
{
if (entityCollection.Entities.Count > 0)
{
int i = 1;
// Trigger the workflow for each entity
foreach (var entity in entityCollection.Entities)
{
service.Execute(new ExecuteWorkflowRequest
{
WorkflowId = workflowEntity.Id,
EntityId = entity.Id
});
Console.WriteLine($"{i++} of {entityCollection.Entities.Count}: Workflow {WORKFLOW_NAME} triggered for entity with ID: {entity.Id}");
}
}
else
{
Console.WriteLine("No entities found based on the query.");
}
}
}
else
{
Console.WriteLine($"No workflow found by name:\"{WORKFLOW_NAME}\"");
}
}
else
{
Console.WriteLine("Failed to connect to Dynamics 365.");
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
Console.WriteLine("Press any key to close.");
Console.ReadLine();
}
}
FetchExpression 和 EntityCollection 原生支持分页。
像这样的东西应该对你有用:
EntityCollection entityCollection = null;
string pagingCookie = null;
int pageNumber = 0;
do
{
pageNumber++;
// Set Paging Cookie
string fetchQuery = SetPagingInformation(FETCH_XML_QUERY, 1000, pageNumber, entityCollection?.PagingCookie ?? String.Empty);
// Execute Fetch
entityCollection = service.RetrieveMultiple(new FetchExpression(fetchQuery));
// Your existing code goes here - just gets repeated for each page
}
while (entityCollection.MoreRecords);
// Helper Method that sets paging info on fetchxml
private string SetPagingInformation(string fetchQuery, int batchSize, int page, string pagingCookie)
{
fetchXml = new XmlDocument();
fetchXml.LoadXml(fetchXml);
fetchXml.DocumentElement.SetAttribute("count", batchSize.ToString());
fetchXml.DocumentElement.SetAttribute("page", page.ToString());
fetchXml.DocumentElement.SetAttribute("paging-cookie", pagingCookie);
return fetchXml.OuterXml;
}
关键点是实体集合中的分页cookie可以嵌入到获取查询中以支持分页。我相信 SDK 中有具体的例子
这是一个微软页面,其中包含更多详细信息: https://learn.microsoft.com/en-us/power-apps/developer/data-platform/org-service/page-large-result-sets-with-fetchxml
您可以手动进行寻呼。您正在获取排序的项目列表,因此记录您获得的姓氏并从那里开始新的获取(名称>=last_name_value)。只需记录您已经处理过的姓氏记录的 ID,这样您就不会对其进行两次处理。