PAYATHON 2026

Dynamics CRM 缺少变更字段时,如何增量同步到 SQL Server?

数据小许

结论

优先检查实体是否支持 Dataverse 的 Change Tracking。缺少 modifiedon 和 versionnumber,不能直接认定该实体无法增量同步。平台的变更跟踪使用同步令牌,不要求客户端通过这两个字段筛选记录。

如果实体不支持 Change Tracking,源端也没有其他可靠的变更日志或事件记录,仅凭 ID 和名称,无法在不重新读取数据的情况下完整识别新增、更新和删除。这种情况下,全量提取后比较差异是合理的兜底方案。

先确认字段和实体能力

示例 FetchXML 只请求了两个属性,不能据此判断其他属性不存在。应先通过实体属性元数据确认字段是否缺失,再检查实体的变更跟踪能力。仅凭 gitorganization 这个名称,无法确定该实体是否支持 Change Tracking。

对于支持相应 Web API 的环境,可以查询:

GET {OrganizationUri}/api/data/v9.2/EntityDefinitions(LogicalName='gitorganization')?$select=LogicalName,EntitySetName,ChangeTrackingEnabled,CanChangeTrackingBeEnabled

这里的 v9.2 是请求示例,应使用实际环境支持的 API 版本。

按以下顺序判断:

  • ChangeTrackingEnabled 为 true:已经启用,可以进一步验证变更读取。
  • 尚未启用,但 CanChangeTrackingBeEnabled.Value 为 true:可以评估启用。
  • 尚未启用,且不允许启用:需要采用其他方案。

Change Tracking 启用后不能关闭,应在启用前确认配置影响。相关能力和限制见 Microsoft Learn:使用变更跟踪同步外部系统。

支持 Change Tracking 时如何接入 SSIS

可以选择 Web API 或 .NET SDK。现有 FetchXML 查询不能代替变更跟踪调用。如果当前 SSIS 组件只提供普通查询,需要使用支持该能力的组件,或通过脚本、独立同步程序调用接口。

Web API 的首次请求示例如下。其中 {EntitySetName} 必须取自元数据,不能自行把逻辑名称变成复数:

GET {OrganizationUri}/api/data/v9.2/{EntitySetName}?$select=gitorganizationid,organizationname
Prefer: odata.track-changes
Accept: application/json

后续使用服务返回的 @odata.deltaLink 读取变化。应完整保存并使用该链接,不要自行拼接令牌。使用 odata.track-changes 时,不支持 $filter、$orderby、$expand 和 $top。同步令牌受保留期限约束,失效后需要重新建立基线。接口说明及限制

如果采用 .NET SDK,则使用 RetrieveEntityChangesRequest。首次读取时建立全量基线,保存响应中的 EntityChanges.DataToken,后续通过 DataVersion 传回。返回的 NewOrUpdatedItem 用于新增或更新,RemovedOrDeletedItem 用于处理移除或删除。调用者需要实体的组织级读取权限。RetrieveEntityChangesRequest 文档

建议按以下步骤组织 SSIS 流程:

  1. 读取该实体上次成功提交的令牌;首次运行时建立基线。
  2. 读取并处理全部分页,将本批数据和删除标记写入暂存区。
  3. 按主键执行幂等的插入、更新和删除。
  4. 目标数据全部提交成功后,再保存新令牌;能够放在同一 SQL Server 事务中的状态更新,应一起提交。

不要在目标数据落库前推进令牌,否则失败重试时可能漏掉尚未写入的数据。重试也应允许重复处理同一批记录。ID 没有出现在某次增量批次中,不代表对应记录已删除;删除必须依据明确的删除信息。

不支持 Change Tracking 时如何处理

如果能够改造源端,可以评估建立持久化变更日志,记录操作类型、主键和可以可靠推进的同步位置。前提是相关实体支持覆盖全部写入路径的变更捕获,尤其是删除操作。不能仅凭实体名称假定这一前提成立。

如果不能提供这样的变更来源,可以继续使用全量暂存和差异比较,并从以下方面降低成本:

  • 只提取主键和确实需要同步的字段。
  • 在暂存表和目标表的主键上建立合适的索引。
  • 只更新属性值发生变化的行,比较时正确处理 NULL。
  • 字段较多时,可以评估行哈希来减少比较成本,但要统一字段序列化规则,并考虑哈希碰撞;它不会减少源端全量读取。
  • 根据业务允许的数据延迟调整全量核对频率。

处理删除时,只有确认本轮全量提取成功、全部分页读取完毕,且读取权限和过滤范围符合预期后,才能将目标表中缺失于源集合的记录视为删除候选。读取失败或权限变化都可能造成“记录消失”的假象。源端在扫描期间持续变化时,也要评估一致性问题,必要时延迟删除并再次核对。

即使实体具有 modifiedon 或 versionnumber,单纯按字段水位查询通常仍不能发现硬删除。因此,这个场景应先解决变更来源和删除捕获,再决定 SSIS 的加载方式。

备注:内容仅供参考。