You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Dynamics CRM VOC中通过C#关联调查问题与响应路由?

解决Dynamics CRM响应路由与问题的关联问题

嘿,我来帮你理清楚怎么在C#代码里关联响应路由(ResponseRouting)和对应的问题。在Dynamics 365 Customer Voice(也就是你说的Dynamics CRM调查模块)里,msdyn_responserouting实体其实自带了两个关键的Lookup属性,专门用来关联问题,只是你可能没注意到它们:

  • msdyn_question: 这个字段指向该响应路由监听的触发问题——也就是触发路由规则的那个问题
  • msdyn_targetquestion: 这个字段指向该路由规则管理的目标问题——也就是路由规则控制显示/隐藏的问题

接下来我会基于你的现有代码,给出具体的关联实现方案。


1. 先修正响应路由的查询逻辑

首先,我建议你明确指定要获取的字段(当然继续用ColumnSet(true)全量获取也可以,但指定字段更高效),确保拿到这两个关联字段:

private static DataCollection<Entity> GetRouting(Guid _surveyId) {
    QueryExpression routingQuery = new QueryExpression {
        EntityName = "msdyn_responserouting", // 这里假设你的query参数传入的是这个标准实体名,如果有自定义实体请替换
        ColumnSet = new ColumnSet("msdyn_name", "msdyn_question", "msdyn_targetquestion", "msdyn_routingtype"),
        Criteria = new FilterExpression {
            Conditions = {
                new ConditionExpression {
                    AttributeName = "msdyn_survey",
                    Operator = ConditionOperator.Equal,
                    Values = {_surveyId}
                }
            }
        }
    };
    return connection.service.RetrieveMultiple(routingQuery).Entities;
}

2. 关联问题与响应路由的核心代码

拿到问题集合和路由集合后,我们可以用字典做快速映射,然后遍历路由关联对应的问题:

// 先获取所有问题,并构建ID到实体的字典,方便快速查找
var surveyQuestions = GetQuestions(yourSurveyId);
var questionLookup = surveyQuestions.ToDictionary(q => q.Id, q => q);

// 获取所有响应路由
var responseRoutings = GetRouting(yourSurveyId);

// 遍历每个路由,关联触发问题和目标问题
foreach (var routing in responseRoutings)
{
    // 处理监听的触发问题
    var triggerQuestionRef = routing.GetAttributeValue<EntityReference>("msdyn_question");
    if (triggerQuestionRef != null && questionLookup.TryGetValue(triggerQuestionRef.Id, out var triggerQuestion))
    {
        // 这里可以把关联结果存入你的自定义模型,或者直接使用
        Console.WriteLine($"路由「{routing["msdyn_name"]}」监听的问题:{triggerQuestion["msdyn_name"]}");
    }

    // 处理管理的目标问题
    var targetQuestionRef = routing.GetAttributeValue<EntityReference>("msdyn_targetquestion");
    if (targetQuestionRef != null && questionLookup.TryGetValue(targetQuestionRef.Id, out var targetQuestion))
    {
        Console.WriteLine($"路由「{routing["msdyn_name"]}」管理的问题:{targetQuestion["msdyn_name"]}");
    }
}

3. (可选)更高效的关联查询:用LinkEntity一次获取所有数据

如果你想减少API调用次数,可以使用LinkEntity在一个查询里同时拉取路由和关联的问题数据:

private static DataCollection<Entity> GetRoutingWithLinkedQuestions(Guid _surveyId) {
    QueryExpression routingQuery = new QueryExpression {
        EntityName = "msdyn_responserouting",
        ColumnSet = new ColumnSet("msdyn_name", "msdyn_routingtype"),
        Criteria = new FilterExpression {
            Conditions = {
                new ConditionExpression {
                    AttributeName = "msdyn_survey",
                    Operator = ConditionOperator.Equal,
                    Values = {_surveyId}
                }
            }
        },
        // 关联触发问题
        LinkEntities = {
            new LinkEntity {
                LinkFromEntityName = "msdyn_responserouting",
                LinkFromAttributeName = "msdyn_question",
                LinkToEntityName = "msdyn_question",
                LinkToAttributeName = "msdyn_questionid",
                Columns = new ColumnSet("msdyn_name", "msdyn_text"),
                EntityAlias = "TriggerQuestion"
            },
            // 关联目标问题
            new LinkEntity {
                LinkFromEntityName = "msdyn_responserouting",
                LinkFromAttributeName = "msdyn_targetquestion",
                LinkToEntityName = "msdyn_question",
                LinkToAttributeName = "msdyn_questionid",
                Columns = new ColumnSet("msdyn_name", "msdyn_text"),
                EntityAlias = "TargetQuestion"
            }
        }
    };
    return connection.service.RetrieveMultiple(routingQuery).Entities;
}

使用这个查询的话,直接从返回结果里拿关联数据即可:

var routedQuestions = GetRoutingWithLinkedQuestions(yourSurveyId);
foreach (var routing in routedQuestions)
{
    var triggerQuestionName = routing.GetAttributeValue<AliasedValue>("TriggerQuestion.msdyn_name")?.Value.ToString();
    var targetQuestionName = routing.GetAttributeValue<AliasedValue>("TargetQuestion.msdyn_name")?.Value.ToString();

    Console.WriteLine($"路由「{routing["msdyn_name"]}」:监听【{triggerQuestionName}】,管理【{targetQuestionName}】");
}

注意事项

  • 确认你的Dynamics环境里msdyn_responserouting实体的字段名称和我说的一致,不同版本的Customer Voice可能略有调整,但核心的关联逻辑是统一的。
  • 如果你的GetRouting方法里的query参数是用来区分不同类型的路由实体,记得替换成对应的实体名称即可。

内容的提问来源于stack exchange,提问作者Headhunter Xamd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:38:02