使用 BizTalk 2013r2 通过 WCF-SQL 存储过程进行 UPSERT

Using BizTalk 2013r2 to UPSERT via WCF-SQL stored procedure

我目前正在尝试为 SQL 数据库中的多个相关 table 编写规范模式,但在评估记录之前是否存在时,我遇到了 DUPLICATE KEY ID 冲突至 UPDATING/INSERTING.

BizTalk 每 5 分钟从学生管理系统接收一次更改记录,将它们映射到一个存储过程,然后调用该过程将更改写入我们的主数据库中的 5 tables。

我认为这是因为我在存储过程中使用了不正确的设计模式。

当前设计:

IF EXISTS (Select student_id FROM student_modules WHERE student_id @student_id and module_id = @module_id)

-- THEN UPDATE THE RECORD

ELSE

-- INSERT THE RECORD

逻辑上这是有道理的,但是因为 BizTalk 同时收到 2 条具有完全相同的学生和模块 ID 的更改记录,然后尝试为每条记录调用存储过程。 SQL 然后恐慌,因为在评估第一条消息中的逻辑时,它会尝试执行 INSERT,同时评估第二条消息中的相同逻辑 - 并告诉我我正在尝试插入 DUPLICATE KEY。 我已经尝试使用我在下面 link(下面的设计)中找到的 UPSERT 模式,但这似乎完全锁定了 student_modules table。

BEGIN TRANSACTION;
 
UPDATE dbo.t WITH (UPDLOCK, SERIALIZABLE) SET val = @val WHERE [key] = @key;
 
IF @@ROWCOUNT = 0
BEGIN
  INSERT dbo.t([key], val) VALUES(@key, @val);
END
 
COMMIT TRANSACTION;

https://sqlperformance.com/2020/09/locking/upsert-anti-pattern

是否有我缺少的更简洁的方法?

您可以使用 MERGE Transact-SQL 命令

INSERT tbl_A (col, col2)  
SELECT col, col2
FROM tbl_B
WHERE NOT EXISTS (SELECT col FROM tbl_A A2 WHERE A2.col = tbl_B.col);  

您还需要考虑更改您的 Orchestration 以便它订阅同一学生 ID 的进一步更新(单例类型模式)或将您的发送端口设置为有序交付,以防止尝试更新相同的学生 ID同时记录。