【发布时间】:2017-06-13 12:40:16
【问题描述】:
我正在尝试将一些 DBIX 事务置于 eval 块下,以便在中间出现问题时进行所有事务或不进行任何事务。
我已经完成了几笔这样的交易,但都没有给我带来问题。只有一个:
我构建交易的方式相当棘手,而且,就其价值而言,这些确实有效。如果你愿意,我可以发布那段代码,但也许 eval 块就足够了:
eval {
for (my $sub = 0; $sub < $neuroexam_index; $sub++){
$transactions{neuroexams}{$sub}->insert;
}
} or die $!;
问题是 eval 在我的控制台中显示错误 ([error] Caught exception in pbitdb::Controller::Subjects->add "Died at /home/lioneluranl/svn/pbitdb/pbitdb/script/../lib/pbitdb/Controller/Subjects.pm line 411."),但实际上执行了插入操作。为什么会这样?
【问题讨论】:
-
“如果中间出现问题,要么进行所有事务,要么不进行任何事务”
eval块不会像数据库事务那样运行,如果这就是你的话重新希望。如果后面的调用失败,任何对insert的调用不会导致异常,则不会回滚。此外,看起来$transactions{neuroexams}应该是一个 array 引用而不是哈希引用。 -
eval { ... } or do { ... };的问题在于它可能会转到do,因为eval中的代码返回错误(可能是合法的),ikegami 的帖子解决了这个问题。另一种方法是显式测试错误eval { }; if ($@) { ... };,在这种情况下返回无关紧要(它不决定它)。 -
@borodin 这很有趣,因为这意味着我对整个 eval 的理解是错误的。我实际上是从另一个正在工作的催化剂应用程序中已经在工作的代码块中获取这个想法的,它的实现方式如上,关于该实现的文档明确表示预期的行为是创建“全有或全无”之类的东西。如果我在子例程中进行事务处理,然后对子例程进行评估以进行更改,会有什么不同吗?
-
@LionelUranLandaburu:在包括 Perl 在内的绝大多数语言中,没有任何东西可以让您自动倒回从特定时间点开始执行的所有操作。 SQL 具有事务 的概念,它正是这样做的,但仅与数据库中的数据相关。显然,Perl 程序可能采取的行动可能会更远,包括全球互联网上的所有系统,并且该程序可能由多个异步线程组成,因此通常无法完成。
-
@LionelUranLandaburu:
eval简单地捕获可能会终止程序的致命错误,并让您有机会编写处理错误的代码。如果您可以编写代码来“撤消”eval块在失败之前的操作,那么它可以在出错的情况下执行。但不会自动发生任何事情。
标签: perl eval catalyst dbix-class