Hello,
I encountered a very similar issue with dependent composite keys when syncing custom tables with Dataverse. The problem here is rooted in how Business Central processes integration field mappings linearly.
Because the standard Job Task table uses a composite primary key (Job No. + Job Task No.), your validation rule on ProjectTaskNo expects the parent ProjectNo to already be settled and matching. During a full sync, the engine is trying to push the parent project code (JOB00010) directly into your task field before the transaction is fully settled, which immediately trips the table relation and crashes the sync block.
To resolve this, I found it best to turn off the immediate inline field validation inside the integration mapping setup. By changing your ValidateField parameter (the 6th parameter) from true to false for the task field, you stop the integration engine from throwing a validation error mid-stream before it has finished transferring all related fields:
GeneralHelper.InsertIntegrationFieldMapping(
'Timesheet-Timesheet',
CX_Timesheet.FieldNo(ProjectTaskNo),
DataverseTimesheet.FieldNo(cr334_ProjectTask),
IntegrationFieldMapping.Direction::Bidirectional, '',
false, // Changed to false to prevent early validation crashes
false);
After disabling the default inline validation, we can safely handle the data validation ourselves once the record fields are fully transferred. I handle this by subscribing to the OnAfterTransferRecordFields event in Codeunit::"Integration Record Synch.". This allows us to double-check the incoming values from Dataverse, ensure the proper task string is assigned, and then manually run the validations in the correct architectural order.
Here is the subscriber code I use to handle this scenario:
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Integration Record Synch.", 'OnAfterTransferRecordFields', '', true, true)]
local procedure HandleTimesheetCompositeKeys(SourceRecordRef: RecordRef; DestinationRecordRef: RecordRef; var AdditionalFieldsModified: Boolean; DestinationIsSource: Boolean)
var
DataverseTimesheet: Record "Dataverse Timesheet"; // Replace with your actual Dataverse table name
CX_Timesheet: Record "CX Timesheet";
begin
if DestinationRecordRef.Number <> Database::"CX Timesheet" then
exit;
// Running when Source is Dataverse and Destination is Business Central
if not DestinationIsSource then begin
SourceRecordRef.SetTable(DataverseTimesheet);
DestinationRecordRef.SetTable(CX_Timesheet);
// If Dataverse is accidentally passing the parent project info into the task field,
// you can manually correct it or safely evaluate it here before final validation
if CX_Timesheet.ProjectTaskNo = CX_Timesheet.ProjectNo then begin
// CX_Timesheet.ProjectTaskNo := DataverseTimesheet.cr334_ActualTaskCodeField;
// Now we validate them in the proper sequential order
CX_Timesheet.Validate(ProjectNo);
CX_Timesheet.Validate(ProjectTaskNo);
DestinationRecordRef.GetTable(CX_Timesheet);
AdditionalFieldsModified := true;
end;
end;
end;
Double-check your Dataverse column data to ensure cr334_ProjectTask is genuinely holding the task code string and not an alternate primary lookup value, and this combination of turning off inline validation and using the post-transfer subscriber will get your sync running smoothly.
Let me know if this solves the issue for you!