在事务中插入父/子记录

时间:2011-01-27 00:06:35

标签: c# oracle transactions parent-child

我有一个C#应用程序,必须按层次顺序插入一条父记录和至少四条子记录。 IOW,父合同适用于一个或多个地点,每个地点有一个或多个物品,每个物品有一个或多个服务,每个服务都有一个或多个要求。应用程序首先获取一组Oracle序列号,每个记录的每个表序列中都有一个序列号。无论出于何种原因(遗留数据库),每条记录不仅包含其父级序列号,还包含合同序列号。

因此,代码开始一个事务,插入带有父级序列号的父代,然后尝试插入位置记录 - 已经填充了父编号作为FK,以及它自己的表序列号。但是,我收到一个Oracle-02291错误,因为找不到父编号而违反了FK。

INSERT into Contracts (contract_sequence_number, ...) values (10437, ...);
INSERT into Locations (location_sequence_number, contract_sequence_number, ...) 
    values (23733, 10437, ...);
...

我猜这是因为父母尚未提交,因此无法使用。但是,如果任何子记录失败,我无法提交父级,因此在子插入之前提交。

我知道这是一个常见的场景,答案必须是pre-noob。但是,到目前为止,我发现的所有答案都暗示父序列号在“表中”中找到,以便满足FK。

对我如何解决这个问题的任何想法都非常感谢。

兰迪

5 个答案:

答案 0 :(得分:1)

子插入将看到任何已提交或先前已由同一事务插入的父级(无论是否已提交)。

要验证的一件事是父项的插入是否自动导出主键值(例如通过触发器)。

也就是说,您发出声明     INSERT into Contracts(contract_sequence_number,...)values(10437,...);

但触发器会从序列中确定一个新的contract_sequence_number,并实际为其提供主键10438(或其他)。

另一个问题可能是任何ORM层通过不以正确的顺序发出插入或使用不同的连接从池中为单个“事务”来解决问题。

同时检查父项的插入没有返回错误。

尝试通过传统客户端(例如SQL * Plus)进行示例事务,看看是否有效。如果子插入失败,只需从合同中查询最近的条目(例如,contract_sequence_number> 10400)并查看插入是否成功。

答案 1 :(得分:1)

将您的fk约束设置为deferrable initially deferred

此外,您需要在单个事务中执行两个/所有插入。如果你正在使用ODAC for C#,那么首先开始OracleTransaction,进行插入,然后是commit()和dispose()。确保在catch块中为事务调用rollback()和dispose()。

有关Oracle数据访问组件的PDF版本(11g),请参阅here

希望有所帮助

答案 2 :(得分:0)

是使用PRAGMA_AUTONOMOUS_TRANSACTION设置完成的任何插入吗?在我看来,挂起的提交应该对整个交易可见。

哦另一个想法 - 如果插入在PRE触发器中,请尝试将它们移动到POST触发器。

答案 3 :(得分:0)

我建议您检查延迟约束,这些约束会在您将数据提交到数据库时检查值,因此您可以避免FK未找到错误

答案 4 :(得分:0)

谢谢大家的意见。原来(我怀疑)这是我的坏事。事实证明,有两个非常相似的模式,我使用的连接可以访问两者。两个模式都具有相同名称的表。由于我不清楚的原因,父母插入一个schmea,但孩子试图插入另一个模式。当然它无法解决PK / FK关系!

再次,谢谢。