【问题标题】:Inserting Parent/Child Records in A Transaction在事务中插入父/子记录
【发布时间】:2011-01-27 00:06:34
【问题描述】:

我有一个 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, ...);
...

我猜这是因为父级尚未提交,因此不可用。但是,如果 any 的子记录失败,则我无法提交父级,因此在子级插入之前进行提交。

我知道这是一个很常见的场景,答案一定是菜鸟。但是,到目前为止,我找到的所有答案都暗示父序列号是在“表中”找到的,以满足 FK。

非常感谢任何关于我如何解决此问题的想法。

兰迪

【问题讨论】:

  • 您不能将插入拆分成两个单独的函数吗?将父记录的 ID 返回到您的 C# 代码,然后使用它来执行子插入?
  • 实际上,它们在同一个事务块中的两个独立函数中。我只是显示两个 SQL 语句来澄清我的问题。

标签: c# oracle transactions parent-child


【解决方案1】:

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

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

也就是说,你发出声明 插入合同 (contract_sequence_number, ...) 值 (10437, ...);

但是触发器从序列中确定了一个新的 contract_sequence_number 并实际上给它主键 10438(或其他)。

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

还要检查父级的插入没有返回错误。

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

【讨论】:

  • 对插入触发器的出色思考。虽然没找到,但我还是问问我们的知识专家吧。
  • 另外,如果孩子在同一个事务中,它应该看到父 ID,这对我来说是有意义的。你知道这对甲骨文来说是否真的如此吗?我的两个插入肯定在同一个事务中,但是我违反了 FK,找不到父项,即使我确认父记录已正确插入。通常如何处理这个父/子问题?
【解决方案2】:

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

此外,您需要在单个事务中执行两个/所有插入操作。如果您将 ODAC 用于 C#,则首先开始 OracleTransaction,执行插入,然后 commit() 和 dispose()。确保在 catch 块中为事务调用 rollback() 和 dispose()。

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

希望有帮助

【讨论】:

  • 谢谢。这几乎就是我正在做的事情。在 C# 中,我开始事务,插入父项,然后尝试插入第一个子项。我不确定我是否可以按照您的建议更改 FK 约束。 DBA 有时并不是最合作的。
  • 哦,是的,我确实有一个回滚。
  • 是的,DBA 应该协助 imo 的开发工作(并最终使公司成为 $$$)。不幸的是,有些人不这么认为......
【解决方案3】:

是否使用 PRAGMA_AUTONOMOUS_TRANSACTION 设置完成了任何插入?在我看来,待处理的提交应该对整个事务可见。

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

【讨论】:

  • 应用程序使用 C# 编写,但保存函数构建 Oracle Command 对象。我将不得不阅读 PRAGMA_AUTONOMOUS_TRANSACTION。以为那纯粹是 Oracle 程序的事情。
  • PRAGMA 不是一件正常的事情,但如果它存在,它肯定会产生与您所描述的情况类似的情况。这里可能没什么好担心的。如果您在触发器之外发出许多顺序插入,那么我建议在每个插入之间进行 COMMIT - 这将允许可见性。
【解决方案4】:

我建议您检查延迟约束,当您将其提交到数据库时,它将检查值,这样您就可以避免 FK not found 错误

【讨论】:

    【解决方案5】:

    感谢大家的意见。结果(正如我怀疑的那样)这是我的错。原来有两个非常相似的模式,我使用的连接可以访问两者。两种模式都有同名的表。由于我不清楚的原因,父母正在插入一个 schmea,但孩子正试图插入另一个模式。当然不能解决PK/FK关系!

    再次感谢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-24
      • 1970-01-01
      • 2015-01-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多