说真的,你怎么能在不发疯的情况下处理所有这些异常呢?我是不是读了太多关于异常处理的文章或什么?我尝试重构了几次,但每次似乎都以更糟糕的结果告终。也许我应该承认确实会发生异常(exception)情况,并且只是享受编写代码的快乐之路? ;) 那么这段代码有什么问题(除了我懒得只是抛出 Exception
而不是更具体的东西这一事实之外)?无论如何,不要对我好过。
public void Export(Database dstDb)
{
try
{
using (DbConnection connection = dstDb.CreateConnection())
{
connection.Open();
DbTransaction transaction = connection.BeginTransaction();
try
{
// Export all data here (insert into dstDb)
transaction.Commit();
}
catch (SqlException sqlex)
{
ExceptionHelper.LogException(sqlex);
try
{
transaction.Rollback();
}
catch (Exception rollbackEx)
{
logger.Error("An exception of type " + rollbackEx.GetType() +
" was encountered while attempting to roll back the transaction.");
}
throw new Exception("Error exporting message " + Type + " #" + Id + ": [" + sqlex.GetType() + "] " + sqlex.Message, sqlex);
}
catch (Exception ex)
{
try
{
transaction.Rollback();
}
catch (Exception rollbackEx)
{
logger.Error("An exception of type " + rollbackEx.GetType() +
" was encountered while attempting to roll back the transaction.");
}
throw new Exception("Error exporting message " + Type + " #" + Id + ": [" + ex.GetType() + "] " + ex.Message, ex);
}
}
try
{
Status = MessageStatus.FINISHED;
srcDb.UpdateDataSet(drHeader.Table.DataSet, HEADERS,
CreateHeaderInsertCommand(), CreateHeaderUpdateCommand(), null);
}
catch (Exception statusEx)
{
logger.ErrorException("Failed to change message status to FINISHED: " +
Type + " #" + Id + ": " + statusEx.Message, statusEx);
}
}
catch (Exception importEx)
{
try
{
Status = MessageStatus.ERROR;
srcDb.UpdateDataSet(drHeader.Table.DataSet, HEADERS,
CreateHeaderInsertCommand(), CreateHeaderUpdateCommand(), null);
}
catch (Exception statusEx)
{
logger.ErrorException("Failed to change message status to ERROR: " +
Type + " #" + Id + ": " + statusEx.Message, statusEx);
}
AddErrorDescription(importEx.Message);
throw new Exception("Couldn't export message " + Type + " #" + Id + ", exception: " + importEx.Message, importEx);
}
}
顺便说一句。很多次,我真的很努力地在形成问题时尽可能具体 - 结果是没有访问,没有答案,也不知道如何解决问题。这一次我一直在想当别人的问题引起我的注意时,我猜这是正确的做法:)
更新:
我已经尝试将一些技巧付诸实践,以下是我到目前为止的想法。我决定稍微改变一下行为:当成功导出后无法将消息状态设置为 FINISHED 时,我认为它是未完全完成的工作,我回滚并抛出异常。如果你们还有一些耐心,请让我知道它是否更好。或者向提出更多批评。顺便提一句。感谢所有的回答,我分析了每一个。
抛出 System.Exception
的实例感觉不对,所以我按照建议放弃了它,而是决定引入自定义异常。顺便说一句,这似乎也不对 - 矫枉过正?这对于公共(public)方法似乎没问题,但对于私有(private)成员来说有点过度设计,但我仍然想知道更改消息状态而不是数据库连接或其他问题存在问题。
我可以在这里看到几种提取方法的方法,但它们似乎都混合了职责 jgauffin在 his comment 中提到:管理数据库连接,处理数据库操作,业务逻辑(导出数据)。比如说 ChangeStatus
方法——它是某种抽象级别——你改变了消息的状态,你对这件事是如何发生的、消息是如何持久化的等不感兴趣。也许我应该使用Data Mapper 模式进一步分离职责,但在这个仍然非常简单的场景中,我认为我会摆脱 Active Record。也许现在整个设计太复杂了,我不知道该从哪里切入?
public void Export(Database dstDb)
{
try
{
using (DbConnection connection = dstDb.CreateConnection())
{
connection.Open();
using (DbTransaction transaction = connection.BeginTransaction())
{
// Export all data here (insert into dstDb)
ChangeStatus(MessageStatus.FINISHED);
transaction.Commit();
}
}
}
catch (Exception exportEx)
{
try
{
ChangeStatus(MessageStatus.ERROR);
AddErrorDescription(exportEx.Message);
}
catch (Exception statusEx)
{
throw new MessageException("Couldn't export message and set its status to ERROR: " +
exportExt.Message + "; " + statusEx.Message, Type, Id, statusEx);
}
throw new MessageException("Couldn't export message, exception: " + exportEx.Message, Type, Id, exportEx);
}
}
private void ChangeStatus(MessageStatus status)
{
try
{
Status = status;
srcDb.UpdateDataSet(drHeader.Table.DataSet, HEADERS,
CreateHeaderInsertCommand(), CreateHeaderUpdateCommand(), null);
}
catch (Exception statusEx)
{
throw new MessageException("Failed to change message status to " + status + ":" + statusEx.Message, statusEx);
}
}
最佳答案
关于c# - 当这么多事情都可能出错时,你所做的就是尝试,尝试,尝试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3148512/