通过工作流更新字段,更好的方法?
Updating a field through workflows, better approach?
我被要求创建一个视图,其中包含适合某个日期范围的实体。因此,如果实体的 new_date1
字段小于今天,而其 new_date2
字段大于今天,则该实体应该出现在表单的子网格中。
遗憾的是,您无法使用简单的视图执行此操作,因为 FetchXML 不支持可能 return 今天日期的计算和运算符。
我想出了在实体上创建一个 Active
字段的想法,然后让 javascript 规则根据输入的日期范围设置该字段。
然后视图可以使用 Active
字段作为过滤条件。
问题是,如果一段时间内未打开实体的表单,实体可能会变得不活动(例如,今天的日期现在已经超过 date1
和 date2
)但是如果用户未打开实体的表单,字段不会自行更新,视图会将非活动实体显示为活动实体。
所以我想到有一个计划的工作流收集所有应该活动或不活动的实体,然后这个工作流启动一个子工作流,将 Active
标志设置为是或否。
下面是一些涉及的代码:
private void LaunchUpdateOpportunityWorkflow(IOrganizationService service, ITracingService tracingService, DataCollection<Entity> collection, bool active)
{
foreach (Entity entity in collection)
{
//launch a different workflow, depending on whether we want it active or inactive...
Guid wfId = (active) ? setActiveWorkflowId : setInactiveWorkflowId;
ExecuteWorkflowRequest execRequest = new ExecuteWorkflowRequest();
execRequest.WorkflowId = wfId;
execRequest.EntityId = (Guid)entity["opportunityid"];
try
{
CrmServiceExtensions.ExecuteWithRetry<ExecuteWorkflowResponse>(service, execRequest);
}
catch (Exception ex)
{
tracingService.Trace(string.Format("Error executing workflow for opportunity {0}: {1}", entity["opportunityid"], ex.Message));
}
}
}
收集相关 DataCollection
的过程是通过简单的 RetrieveMultipleRequest
请求完成的。
该方法的问题在于,如果服务器重新启动,则必须有人去启动运行上述代码的工作流。
有更好的方法吗?我正在使用 MS CRM 2016。
我认为您可以使用 FetchXML 实现此目的。
new_date1
field is lesser than today
这超过 24 小时。
new_date2
field is greater than today
这是未来的任何日期,因此假设您的日期不超过未来 100 年,您可以使用 Next X Years。
正如 Darren Lewis 指出的那样,根据您对昨天的定义,超过 24 小时的时间可能不是昨天。在这种情况下尝试使用过去 X 年。
添加到 Jame 的回答中,如果过滤条件变得复杂而无法使用 fetchxml 实现,您始终可以使用插件。
在 "RetrieveMultiple" 消息上注册一个插件。
var queryExpression = PluginExecutionContext.InputParameters["Query"];
if(queryExpression == null || !queryExpression.EntityName.equals("yourentityname", StringComparison.InvariantCultureIgnoreCase) return;
添加一个高级查找独有的条件,因为无法过滤出哪个高级查找触发了您实体上的插件,实现此目的的最简单方法是添加一个属性并使用它在高级查找查询中。
检查条件,如果找到,则用户正在尝试 运行 您设置的高级查找:
if (queryExpression.Criteria == null || queryExpression.Criteria.Conditions == null ||
!queryExpression.Criteria.Conditions.Any()) return;
找到匹配的条件,这样您就可以删除它并添加您希望按以下条件过滤数据的条件:
var matchContidion = queryExpression.Criteria.Conditions.FirstOrDefault(c => c.AttributeName == "yourflagattribute");
if (matchContidion == null) return;
删除虚拟匹配条件并添加您自己的条件:
queryExpression.Criteria.Conditions.Remove(matchContidion);
queryExpression.Criteria.Conditions.Add(new ConditionExpression("new_date1", ConditionOperator.LessThan, DateTime.Now));
queryExpression.Criteria.Conditions.Add(new ConditionExpression("new_field2", ConditionOperator.Equals, "Some complex value which cannot be set using fetchxml")); //for example, based on certain values, you might want to call a webservice to get the filter value.
我被要求创建一个视图,其中包含适合某个日期范围的实体。因此,如果实体的 new_date1
字段小于今天,而其 new_date2
字段大于今天,则该实体应该出现在表单的子网格中。
遗憾的是,您无法使用简单的视图执行此操作,因为 FetchXML 不支持可能 return 今天日期的计算和运算符。
我想出了在实体上创建一个 Active
字段的想法,然后让 javascript 规则根据输入的日期范围设置该字段。
然后视图可以使用 Active
字段作为过滤条件。
问题是,如果一段时间内未打开实体的表单,实体可能会变得不活动(例如,今天的日期现在已经超过 date1
和 date2
)但是如果用户未打开实体的表单,字段不会自行更新,视图会将非活动实体显示为活动实体。
所以我想到有一个计划的工作流收集所有应该活动或不活动的实体,然后这个工作流启动一个子工作流,将 Active
标志设置为是或否。
下面是一些涉及的代码:
private void LaunchUpdateOpportunityWorkflow(IOrganizationService service, ITracingService tracingService, DataCollection<Entity> collection, bool active)
{
foreach (Entity entity in collection)
{
//launch a different workflow, depending on whether we want it active or inactive...
Guid wfId = (active) ? setActiveWorkflowId : setInactiveWorkflowId;
ExecuteWorkflowRequest execRequest = new ExecuteWorkflowRequest();
execRequest.WorkflowId = wfId;
execRequest.EntityId = (Guid)entity["opportunityid"];
try
{
CrmServiceExtensions.ExecuteWithRetry<ExecuteWorkflowResponse>(service, execRequest);
}
catch (Exception ex)
{
tracingService.Trace(string.Format("Error executing workflow for opportunity {0}: {1}", entity["opportunityid"], ex.Message));
}
}
}
收集相关 DataCollection
的过程是通过简单的 RetrieveMultipleRequest
请求完成的。
该方法的问题在于,如果服务器重新启动,则必须有人去启动运行上述代码的工作流。
有更好的方法吗?我正在使用 MS CRM 2016。
我认为您可以使用 FetchXML 实现此目的。
new_date1
field is lesser than today
这超过 24 小时。
new_date2
field is greater than today
这是未来的任何日期,因此假设您的日期不超过未来 100 年,您可以使用 Next X Years。
正如 Darren Lewis 指出的那样,根据您对昨天的定义,超过 24 小时的时间可能不是昨天。在这种情况下尝试使用过去 X 年。
添加到 Jame 的回答中,如果过滤条件变得复杂而无法使用 fetchxml 实现,您始终可以使用插件。
在 "RetrieveMultiple" 消息上注册一个插件。
var queryExpression = PluginExecutionContext.InputParameters["Query"];
if(queryExpression == null || !queryExpression.EntityName.equals("yourentityname", StringComparison.InvariantCultureIgnoreCase) return;
添加一个高级查找独有的条件,因为无法过滤出哪个高级查找触发了您实体上的插件,实现此目的的最简单方法是添加一个属性并使用它在高级查找查询中。
检查条件,如果找到,则用户正在尝试 运行 您设置的高级查找:
if (queryExpression.Criteria == null || queryExpression.Criteria.Conditions == null ||
!queryExpression.Criteria.Conditions.Any()) return;
找到匹配的条件,这样您就可以删除它并添加您希望按以下条件过滤数据的条件:
var matchContidion = queryExpression.Criteria.Conditions.FirstOrDefault(c => c.AttributeName == "yourflagattribute");
if (matchContidion == null) return;
删除虚拟匹配条件并添加您自己的条件:
queryExpression.Criteria.Conditions.Remove(matchContidion);
queryExpression.Criteria.Conditions.Add(new ConditionExpression("new_date1", ConditionOperator.LessThan, DateTime.Now));
queryExpression.Criteria.Conditions.Add(new ConditionExpression("new_field2", ConditionOperator.Equals, "Some complex value which cannot be set using fetchxml")); //for example, based on certain values, you might want to call a webservice to get the filter value.