Серьезно, как вы можете обрабатывать все эти исключения, не сходя с ума?Я прочитал слишком много статей об обработке исключений или что?Я пробовал рефакторинг пару раз, и каждый раз, кажется, что-то получалось еще хуже.Может быть, я должен признать, что исключения случаются, и просто наслаждаться кодированием просто happy path ?;) Так что же не так с этим кодом (кроме того, что мне лень было просто выбросить 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);
}
}
Кстати.Столько раз я очень старался быть максимально конкретным при формулировании вопросов - в результате не было ни посещений, ни ответов, ни идей о том, как решить проблему.На этот раз я подумал о тех случаях, когда чей-то вопрос привлек мое внимание, думаю, это было правильно:)
Обновление:
Я пыталсяприменение некоторых советов на практике, и вот что я придумал до сих пор.Я решил немного изменить поведение: когда после успешного экспорта невозможно установить статус сообщения на ЗАВЕРШЕНО, я рассматриваю это как работу, выполненную не полностью, и откатываю и выкидываю исключение.Если у вас, ребята, осталось немного терпения, пожалуйста, дайте мне знать, если это будет лучше.Или бросить еще немного критики на меня.Btw.Спасибо за все ответы, я анализирую каждый из них.
Бросать экземпляр System.Exception
не чувствовал себя хорошо, поэтому я избавился от этого, как было предложено, и вместо этого решил ввести обычайисключение.Это, кстати, тоже не кажется правильным - перебор?Похоже, что это нормально для общедоступных методов, но немного перегружено для частного члена, но все же я хочу знать, что была проблема с изменением статуса сообщения вместо проблемы с подключением к базе данных или чем-то еще.
IЗдесь можно увидеть несколько способов извлечения методов, но все они, кажется, смешивают обязанности, которые jgauffin упоминали в его комментарии : управление подключением к базе данных, обработка операций с базой данных, бизнес-логика (экспорт данных).Скажем, метод 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);
}
}