对于使用WCF-OracleDB适配器在事务中进行轮询,我有一个普遍的问题,以确保被轮询的一(或多个)行也被更新为仅轮询一次。
在WCF-SQL中,我通常使用轮询(可用)语句。在PollingAvailableStatement中,我使用一个简单的COUNT(*)查询。在PollingStatement中,我通常查询下一行并在本地存储其ID。然后,我既查询数据又用状态更新行,以确保被轮询的行不再被轮询。而且,如果出现问题,则AmbientTransaction会将其回滚。
如何使用PostPollingStatement通过WCF-OracleDB-adapter实现相同的目的?我想念的是对我轮询的行的“引用”,以确保只有正确的行才能获得更新状态。
我当然尝试用Google搜索,但是每个人似乎都避免了这一要求...?
答案 0 :(得分:0)
我无法在Oracle中找到任何功能组合来使用与SQL Server相同的解决方案,该解决方案具有更新轮询状态和返回数据的过程。因此,必须有另一种解决方案来针对Oracle数据库进行安全轮询。
Oracle有两种事务隔离级别模式,您需要使用 Serializable 才能使轮询正常工作。我认为这就像您进入序列化模式时所获得的数据库的“快照”。如果使用ReadCommitted,您将不受其他用户所做更改的影响。提交时,其他用户将看到您的更改,而您也会看到他们的更改。为了避免其他用户在可序列化模式下进行干扰,请确保使用 FOR UPDATE 锁定行。当您(或BizTalk)提交更改时,它将被释放。
底线,在可序列化模式下,相同的查询将始终返回相同的结果(如果您自己未更改的话)。这样,您就可以只更新以前轮询的行,即我的问题中缺少的“引用”。
此外,必须使用 UseAmbientTransaction 来确保BizTalk在出现问题时能够成功回滚事务。某些人建议不要使用PRAGMA AUTONOMOUS_TRANSACTION,因为它是子事务,BizTalk启动的事务无法回滚。
注意: EnableBizTalkCompatibilityMode 也应设置为True,但是我有 找不到原因或作用的任何解释。
因此,使用上述设置配置,WCF-OracleDB适配器将在执行PollingStatement之前自动进入可序列化模式,您将能够使用与PollingStatement相同的查询来接收数据并更新轮询状态,并且如果PostPollingStatement为成功。否则,AmbientTransaction将确保您的更改未提交。
并且,配置轮询语句:
PollingAvailableStatement
SELECT COUNT(*) FROM <Table> WHERE POLLED = 0
投票声明
SELECT * FROM <Table> WHERE POLLED = 0 ORDER BY Date ASC FOR UPDATE
PostPollingStatement
UPDATE <Table> SET POLLED = 1 WHERE POLLED = 0
在现实世界中,您可能还必须考虑批处理(在Oracle中使用ROWNUM),这意味着您需要构建类似于以下内容的查询:
SELECT *
FROM <Table>
WHERE PK IN
(
SELECT PK
FROM (
SELECT *
FROM <Table>
WHERE POLLED = 0
ORDER BY PK ASC
)
WHERE ROWNUM <=10
)
FOR UPDATE;
和:
UPDATE <Table>
SET POLLED = 1
WHERE PK IN
(
SELECT PK
FROM (
SELECT *
FROM <Table>
WHERE POLLED = 0
ORDER BY PK ASC
)
WHERE ROWNUM <=10
)
这里的要点是必须先执行WHERE和ORDER BY,然后ROWNUM才基于该子查询(或视图)。