В итоге решил это дело так. На место {0} в C# коде подставляется сгенерированный GUID
BEGIN TRANSACTION
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
SET DEADLOCK_PRIORITY LOW;
DECLARE @Quantity INT = 5;
IF OBJECT_ID('tempdb..##GroupIDs_{0}') IS NULL
BEGIN
CREATE TABLE ##GroupIDs_{0} (
ID INT NOT NULL,
CONSTRAINT PK_GroupIDs_ID_{0} PRIMARY KEY(ID),
);
END
INSERT INTO ##GroupIDs_{0} (ID)
SELECT TOP(@Quantity) ID FROM SOME_GROUP WITH(UPDLOCK, READPAST) WHERE REPLICATED <> 1
-- Первый запрос, вызываемый из C# кода в одной транзакции.
-- 1 ------------------------------------------------------------------
UPDATE SOME_GROUP SET REPLICATED = 2
OUTPUT
INSERTED.ID
,INSERTED.NAME
WHERE ID IN(SELECT ID FROM ##GroupIDs_{0})
-- Второй запрос, вызываемый из C# кода в одной транзакции.
-- 2------------------------------------------------------------------
UPDATE SOME_CHILD_ONE SET REPLICATED = 2
OUTPUT
INSERTED.ID
,INSERTED.GROUP_ID
,INSERTED.UPDATED
WHERE GROUP_ID IN(SELECT ID FROM ##GroupIDs_{0}) AND REPLICATED <> 1
-- Третий запрос, вызываемый из C# кода в одной транзакции.
-- 3 ------------------------------------------------------------------
UPDATE SOME_CHILD_TWO SET REPLICATED = 2
OUTPUT
INSERTED.ID
,INSERTED.GROUP_ID
,INSERTED.NAME
,INSERTED.CREATED
WHERE GROUP_ID IN(SELECT ID FROM ##GroupIDs_{0}) AND REPLICATED <> 1
DROP TABLE ##GroupIDs_{0};
-- 3 ------------------------------------------------------------------
COMMIT TRANSACTION