发生异常时如何访问数据库数据?

How to access database data when exception occur?

我有下一个代码:

my $savepoint =  $c->db->txn_scope_guard;
return $self->render( 'subnet/create',  error => [ create => $@ ],
    servers =>  $self->rows( 'Server' )->lookup,
) unless $subnet =  eval{ $self->rows( 'Subnet' )->create( $subnet ) };
$savepoint->commit;

这里 rows 是提供数据访问的 Mojolicious 助手。

sub model {
    my( $c, $table_name ) =  (shift,shift);

    return $c->db->resultset( $table_name );
}

->db也是帮手:

sub db { return $schema
    //=  DBIx::Class::Schema->connect( $DB->{ DSN },  @$DB{ qw/ USER PASS / },  {
        AutoCommit => 1,
        RaiseError => 1,
        quote_char => '"',
    })
});

当我创建 $subnet 并且出现唯一约束时(这里不管出现哪个约束,实际上是在任何异常的情况下)我得到了错误:

DBIx::Class::Storage::DBI::_dbh_execute(): DBI Exception: DBD::Pg::st execute failed: ERROR:  current transaction is aborted, commands ignored until end of transaction block [for Statement "SELECT "me"."id", "me"."hostname" FROM "servers" "me" ORDER BY hostname"] at ...

这是当我用 eval{ ... } 捕获异常时,当前事务已中止,我无法执行 $self->rows( 'Server' )->lookup

有没有办法在发生异常后访问服务器数据?

看来我找到了答案,因为更仔细地阅读了错误信息:

... commands ignored until end of transaction block

所以当异常发生时我强制结束事务块:

$c->db->txn_rollback;

代码:

my $savepoint =  $c->db->txn_scope_guard;
unless( $subnet =  eval{ $self->rows( 'Subnet' )->create( $subnet ) } ) {
    my $e = $@; # $@ may be changed before `create => $@`
    undef $savepoint; # Or the same: $c->db->txn_rollback;     
    return $self->render( 'subnet/create',  error => [ create => $e ],
        servers =>  $self->rows( 'Server' )->lookup,
    );
}
$savepoint->commit;