更新catch块

时间:2017-07-12 02:52:41

标签: exception exception-handling language-agnostic

我有以下代码

try {

  //Some code here that could throw an exception

 } catch (Exception e) {

  //handleExc contains code to Update the database

  handleExc();

 }

如果抛出异常,我正在尝试更新数据库。 但我的问题是更新catch块内的数据库也可能引发异常。

handleExc()方法包含在引发意外异常时更新数据库中的行的代码。 我确保它一直有效。

但是,现在我开始思考,

  • 如果数据库关闭(假设)怎么办?我的托管服务提供商不可行
  • 如何在这种情况下处理异常,因为我有更新catch块内数据库的语句

我知道可以在catch块中抛出异常的语句的异常不会被捕获吗?

是否有一种我不知道的优雅方式,可以在这种情况下使用?

PS。我正在使用C#和asp.net以及sqlserver,但我猜我的问题可以推广到任何编程语言

1 个答案:

答案 0 :(得分:0)

这就是数据库(包括MS SQL Server)支持事务的原因。

您正在尝试重新发明交易,但是从客户端执行。您正在讨论的部分是“回滚”阶段。数据库实现了这一点,因为在客户端代码中没有真正的方法可以实现它并确保其正常工作。

使用真实事务,您可以指定一系列所有需要以原子方式一起执行的操作 - 数据库服务器确保所有事情都发生(就好像它们都是一次完成的)或者没有他们发生了。

基本思想看起来像这样:

begin transaction
change A
change B
change C
commit transaction

如果在(比方说)更改C期间出现问题,则事务将永远不会被提交,之后数据库将处于相同的状态,就像更改A和更改B从未发生过一样。

基本上,你在客户端试图破解的任何东西最终都会遇到问题 - 或者更确切地说,主要是一个问题:无论try / catch多少级别阻止你尝试嵌套,你总是有可能做了以后需要撤消的事情,如果你失去了与服务器的连接,你就不能再撤消了。更糟糕的是,即使没有出现任何问题,您也可能最终导致数据库暂时不一致,例如说某些库存已经消失而没有收到付款(反之亦然)。

设计良好的数据库通常使用事务日志来实现事务。这意味着它首先记录交易所需的内容。然后它开始执行事务指定的更改。如果(例如)数据库服务器在事务中间断电,当它开始备份时,它可以将数据库回滚到最后一个部分事务开始之前的状态,然后它可以重放事务日志从那里前进。

我会再说一遍:客户端无法做的就是为您的数据提供这种级别的保护。

那就是说,让我们考虑在一些不涉及数据库的其他情况下你需要做些什么。您需要做的主要事情是决定您真正希望做什么。如果您已经完成了以后需要撤消的操作,但撤消步骤可能会抛出异常,那么您将决定要执行的操作。

大多数语言都允许您在try内嵌入catch

try { 
   make change A
}
catch (foo) {
    try { 
       undo change A
    }
    catch (bar) {
        // what to do now?
    }
}

很有可能在catch (bar)块内你可以做的就是警告你的用户事情已经发生了可怕的错误,然后记录错误以通知你需要修复的东西。如果它是(例如)与服务器的不可连接的连接,那么可能想等待一点点并重试。