Самый сухой способ сделать это - написать вспомогательный метод, который принимает делегат, текст команды sql и, необязательно, массив параметров sql, если вы используете параметризованные запросы. Оберните делегата в блок try catch и вызовите метод LogError, когда возникнет исключение:
protected virtual TResult ExecuteAndLogError<TResult>(Func<TResult> code, string sql, SqlParameterCollection parameters = null)
{
try {
if ((System.Diagnostics.Debugger.IsAttached))
PrintSqlToDebug(sql, parameters);
return code();
} catch (Exception ex) {
LogError(sql, parameters, ex);
throw;
}
}
В моем коде SQL я вызываю ExecuteAndLogError из вспомогательных методов уровня данных. Все методы уровня данных вызывают ExecuteAndLogError, поэтому для регистрации ошибок SQL существует только один раздел кода.
public virtual DataTable ExecuteDataTable(SqlCommand command, params SqlParameter[] parameters)
{
command.Parameters.AddRange(parameters);
DataTable table = new DataTable();
using (SqlDataAdapter adapter = new SqlDataAdapter(command)) {
using (command) {
ExecuteAndLogError(() => adapter.Fill(table), command.CommandText, command.Parameters);
}
}
return table;
}
Вы можете использовать его следующим образом: repo.ExecuteDataTable("SELECT * FROM Users");
Если есть исключение, вы можете реализовать метод LogError для выполнения дополнительной регистрации.
Часть этого кода была взята из классов слоя данных Subtext Blog.