2017-01-27 18 views
2

Я пытаюсь поместить некоторые транзакции DBIX под блоком eval, чтобы сделать все транзакции или нет, если что-то пойдет не так в середине.perl eval block throwing execptions без ошибок

У меня есть несколько транзакций, которые выполняются так, и никто из них не дает мне проблем. Ни один, кроме одного:

Способ построения транзакций довольно сложный и, для чего он стоит, они действительно работают. Я могу опубликовать этот кусок кода, если вы хотите, но, возможно, блок 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.") в моей консоли, но на самом деле выполняет вставки. Почему это так?

+5

* "либо делать все транзакции, либо ничего, если что-то не так в середине" * Блок 'eval' не будет действовать как транзакция базы данных, если это то, что вы надеетесь. Любые вызовы 'insert', которые не вызывали исключение, не будут откатываться, если последует ошибка. Кроме того, похоже, что '$ transaction {neuroexams}' должно быть ссылкой * array *, а не ссылкой на хеш. – Borodin

+0

Проблема с 'eval {...} или do {...};' заключается в том, что она может перейти к 'do' из-за (возможно легитимного) ложного возврата из кода в' eval', что решает вопрос ikegami. Другой способ - явно проверить ошибку, 'eval {}; if ($ @) {...}; ', и в этом случае возврат не имеет значения (он не принимает решения об этом). – zdim

+0

@borodin это очень интересно, потому что это означает, что я понял, что все это неправильно. Я фактически взял идею из уже работающего блока кода в другом приложении для каталогов на работе, и он был реализован, как указано выше, и в документации, касающейся этой реализации, явным образом сказал, что ожидаемое поведение состояло в том, чтобы создать «все или ничего». Было бы иначе, если бы я совершил транзакции в подпрограмме, а затем вычислил подпрограмму для изменения? –

ответ

9
eval { 
    for (my $sub = 0; $sub < $neuroexam_index; $sub++){ 
    $transactions{neuroexams}{$sub}->insert; 
    } 
    1; # No exception. 
} 
    or do { 
    # ... Perform rollback here ... 
    die("[error] Caught exception in pbitdb::Controller::Subjects->add: [email protected]"); 
    }; 

или

if (!eval { 
    for (my $sub = 0; $sub < $neuroexam_index; $sub++){ 
    $transactions{neuroexams}{$sub}->insert; 
    } 
    1; # No exception. 
}) { 
    # ... Perform rollback here ... 
    die("[error] Caught exception in pbitdb::Controller::Subjects->add: [email protected]"); 
} 

Три изменения:

  • 1; был добавлен, чтобы обеспечить истинное значение возвращается, когда не является исключением для обеспечения RHS в or не оценивается ,
  • Исключенное исключение найдено в [email protected], а не $!. ($! соответствует errno, код ошибки, заданный вызовами библиотеки C и системными вызовами.)
  • Ловля исключения, чтобы просто перебросить его бесполезно. Кажется, вы хотите поймать исключение, чтобы обернуть сообщение об исключении, но вы этого не делали. Вы также упоминаете транзакции базы данных, поэтому я предполагаю, что вы хотите выполнить откат по исключению.
+0

Спасибо за подсказку :). Теперь, добавив, что «1» не заставит eval игнорировать, произошла ли ошибка выше? Просто протестируйте его, и теперь никакие исключения не выбрасываются с помощью 1, но удаление этого приведет к тому, что исключение будет сброшено снова. Это безопасно? –

+4

Он не достигнет '1', если в блоке произошло исключение. – ikegami

+0

Это умный xD. Ну, спасибо большое. Проблема исправлена ​​ –

 Смежные вопросы

  • Нет связанных вопросов^_^