Я столкнулся с той же проблемой в моем приложении ASP.NET MVC 4.
То, как я это решил, было в DatabaseContext
. Передавая имя строки подключения, которую я хотел использовать через базовый конструктор.
public class DatabaseContext : DbContext
{
public DatabaseContext()
: base("DefaultConnection") // <-- this is what i added.
{
}
public DbSet<SomeModel> SomeModels { get; set; }
}
Это небезопасно полагаться на то, что в документации объявлено устаревшим. Поведение может (и, вероятно, изменится) в будущем выпуске. Опора на устаревшее поведение привязывает вас к той версии Perl, которую вы используете сегодня.
К сожалению, я не вижу способа обойти это, что соответствует вашим критериям. «Правильное» решение - изменить внутренние методы для вызова Carp :: confess
вместо die
и удалить собственный обработчик $ SIG {__ DIE __}
.
use strict;
use warnings;
use Carp qw'confess';
outer();
sub outer { middle(@_) }
sub middle { eval { inner() }; die $@ if $@ }
sub inner { confess("OH NOES!") }
__END__
OH NOES! at c:\temp\foo.pl line 11
main::inner() called at c:\temp\foo.pl line 9
eval {...} called at c:\temp\foo.pl line 9
main::middle() called at c:\temp\foo.pl line 7
main::outer() called at c:\temp\foo.pl line 5
Поскольку вы все равно умираете, возможно, вам не нужно перехватывать вызов inner ()
. (В вашем примере этого нет, ваш фактический код может отличаться.)
В вашем примере вы пытаетесь вернуть данные через $ @
. Вы не можете этого сделать. Вместо этого используйте
my $x = eval { inner(@_) };
. (Я предполагаю, что это просто ошибка упрощения кода, достаточная для того, чтобы опубликовать его здесь.)
ОБНОВЛЕНИЕ: Я изменил код, чтобы переопределить die
глобально, чтобы также можно было перехватить исключения из других пакетов.
Имеет ли следующие действия делают то, что вы хотите?
#!/usr/bin/perl
use strict;
use warnings;
use Devel::StackTrace;
use ex::override GLOBAL_die => sub {
local *__ANON__ = "custom_die";
warn (
'Error: ', @_, "\n",
"Stack trace:\n",
Devel::StackTrace->new(no_refs => 1)->as_string, "\n",
);
exit 1;
};
use M; # dummy module to functions dying in other modules
outer();
sub outer {
middle( @_ );
M::n(); # M::n dies
}
sub middle {
eval { inner(@_) };
if ( my $x = $@ ) { # caught exception
if (ref $x eq 'ARRAY') {
print "we can handle this ...";
}
else {
die $x; # rethrow
}
}
}
sub inner { die "OH NOES!" }
Обратите внимание, что переопределение die
будет перехватывать только фактические вызовы к die
, not Ошибки Perl, такие как разыменование undef
.
Я не думаю, что общий случай возможен; весь смысл eval
состоит в том, чтобы поглотить ошибки. Вы МОЖЕТЕ быть в состоянии полагаться на устаревшее поведение именно по этой причине: на данный момент другого способа сделать это нет. Но я не могу найти какой-либо разумный способ получить трассировку стека в каждом случае, не нарушая код обработки ошибок, который уже существует, но далеко внизу стека.