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

C#开发CRM插件:拼接字段时未修改属性取值为空问题

问题根因

Dataverse(Dynamics CRM) 插件处理Update请求时,InputParameters 中的Target实体仅会携带本次操作中被修改的字段,未改动的字段不会出现在Target的Attributes集合中,直接从Target读取未修改字段必然得到空值,这是平台的默认运行机制,不是运行异常。原有代码还存在无效逻辑:将Update场景的上下文参数直接传入CreateRequest对象取Target,属于冗余无效操作,不会返回正确结果。

正确实现方案

核心逻辑是把「本次提交的修改值」和「数据库中存储的未修改字段值」合并,拿到两个电话字段的最终值后再拼接赋值,具体实现要点:

  • 从Target实体中获取当前更新记录的主键Id,所有Update请求的Target一定会携带记录Id
  • 调用组织服务的Retrieve方法查询数据库中该记录的当前存储值,查询时只指定需要用到的telephone1、telephone2字段,避免全字段查询带来的性能损耗
  • 两个电话字段的取值逻辑:如果本次更新修改了对应字段,优先取Target中的新值;如果未修改,取Retrieve查到的数据库存量值
  • 插件必须注册在Update消息的PreOperation阶段,该阶段修改Target实体的属性后,会随本次更新请求直接提交到数据库,不需要额外调用service.Update,既减少一次IO请求,也能避免触发插件递归死循环

字段更新异常参考截图

修正后的代码
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
    try
    {
        Entity entityInput = (Entity)context.InputParameters["Target"];
        Guid recordId = entityInput.Id;

        // 仅查询业务需要的字段,最小化查询开销
        ColumnSet columnSet = new ColumnSet("telephone1", "telephone2");
        Entity currentRecord = service.Retrieve(entityInput.LogicalName, recordId, columnSet);

        // 优先取本次更新的新值,未传值则取数据库存储的未修改值
        string telephone1 = entityInput.Contains("telephone1") 
            ? entityInput.GetAttributeValue<string>("telephone1") 
            : currentRecord.GetAttributeValue<string>("telephone1");
        string telephone2 = entityInput.Contains("telephone2") 
            ? entityInput.GetAttributeValue<string>("telephone2") 
            : currentRecord.GetAttributeValue<string>("telephone2");

        // 空值兜底,避免拼接出"null;xxx"这类异常格式
        telephone1 ??= string.Empty;
        telephone2 ??= string.Empty;
        entityInput["telephone3"] = $"{telephone1};{telephone2}";

        // PreOperation阶段不需要额外调用service.Update,修改会随当前请求直接提交
    }
    catch (Exception ex)
    {
        throw new InvalidPluginExecutionException($"拼接telephone3字段出错:{ex.Message}", ex);
    }
}
else
{
    throw new InvalidPluginExecutionException($"插件 {nameof(Class1)} 注册配置错误,未获取到目标实体");
}
注意事项
  • 不要把插件注册在PostOperation阶段后再调用service.Update提交telephone3的值,该方式会触发两次记录更新,还可能导致插件递归触发形成无限循环
  • 所有实体字段取值前必须做存在性判断,不要直接通过entityInput.Attributes["字段名"]的方式取值,字段不存在时会直接抛出KeyNotFoundException
  • 字符串拼接前要做空值兜底,避免把null值直接拼入结果,出现不符合预期的格式

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 04:30:51