I have the following code:
public IDictionary<string, string> GetNextBase36(string partitionKey, string rowKey, ref string seq)
{
Sequence sequence;
try {
sequence = _sequenceRepository.Get(u => u.PartitionKey == partitionKey & u.RowKey == rowKey);
} catch {
_errors.Add("", "Database error: Get sequence failed");
}
try {
sequence.Value = Base36.Encode(Base36.Decode(sequence.Value) + 1);
_sequenceRepository.AddOrUpdate(sequence);
seq = sequence.Value;
} catch {
_errors.Add("", "Database error: Updating sequence failed");
}
return _errors;
}
It works but it seems overkill to have each database access surrounded by a try catch block. Is there some way I could simplify this? Is there any beter approach?
Updated code based on help / advice:
public IDictionary<string, string> GetNextBase36(string partitionKey, string rowKey, ref string seq)
{
Sequence sequence;
string catchMsg = string.Empty;
try {
catchMsg = "Database error: Get sequence failed"
sequence = _sequenceRepository.Get(u => u.PartitionKey == partitionKey & u.RowKey == rowKey);
sequence.Value = Base36.Encode(Base36.Decode(sequence.Value) + 1);
catchMsg = "Database error: Updating sequence failed"
_sequenceRepository.AddOrUpdate(sequence);
seq = sequence.Value;
} catch {
_errors.Add("", catchMsg);
}
return _errors;
}
You are sacrificing exact exception stack traces on the altar of error message readability (not to mention code readability).
Consider your audience: a developer. A developer should be able to read an exception stack trace, which is much more valuable debugging information than a short error message.
Hence my suggestion is to only put in one exception handler for logging somewhere higher up the hierarchy. If you have to have one in your current method, at least capture the full exception stack trace.
Also - does it really make sense to continue after the first exception? If retrieving the sequence fails, using its value in the next try block won't fair any better. It does not make sense having multiple try/catch blocks here, unless you know exactly how to solve the problem in each catch handler so you can continue.
Update:
Now that you have a single try/catch block code readability is improved. It still looks very odd that you are basically returning a list of errors to the caller - the error case should be exceptional, so it should not bleed into the business logic of your method, instead I would just let the exception go up the stack until you can truly handle the problem (or just log it and exit the app).
Your code should ideally look something like this (I will be inventing class names here and there): i.e. you should have one try block and multiple handlers which depend on the type of exception raised.
The reason why you should have only one try block is that, as pointed out by others, the two queries are related, and you should not perform the update if the select has gone wrong.
public IDictionary<string, string> GetNextBase36(string partitionKey, string rowKey, ref string seq)
{
Sequence sequence;
try {
sequence = _sequenceRepository.Get(u => u.PartitionKey == partitionKey & u.RowKey == rowKey);
sequence.Value = Base36.Encode(Base36.Decode(sequence.Value) + 1);
_sequenceRepository.AddOrUpdate(sequence);
seq = sequence.Value;
} catch( SelectException e ) {
_errors.Add("", "Database error: Get sequence failed");
} catch( UpdateException e ) {
_errors.Add("", "Database error: Updating sequence failed");
} catch {
_errors.Add("", "Database error: Something really bad happened!");
}
return _errors;
}
If you fail to get the item from the database, does it make sense that you should attempt to update it? Wrap the whole thing in a single try { ... } catch () block if you intend to handle/translate exceptions at that point in your code.
Related
I have a piece of code that sometimes throws an exception and sometimes doesn't. Depending on IO and network, different kinds of exception might be thrown. I have a wrapper for that code that shall retry the failing statement, say 10 times until it succeeds. If the exception does not go away after the 10th time, I rethrow it. Until now, I know what to do. Currently, I have something like this:
private void ExecuteStatement(Action statementToExecute)
{
while (true)
{
int exceptionCount = 0;
try
{
statementToExecute.Invoke();
// statement finished successfully
break;
}
catch (Exception e)
{
if (!IsFrameworkException(e))
throw; // rethrow as it isn't a framework exception
// we know now that it's a framework exception
exceptionCount++;
if (exceptionCount >= MaxRetriesOnFrameworkException)
throw;
}
}
}
The issue is the following: I want to reset the counter in case the exception changes (i. e. different type, different stacktrace, different message). I know how to compare them individually, but I want to know if there's a standard C# way of accomplishing this.
Edit: Here's the code of IsFrameworkException:
private bool IsFrameworkException(Exception e)
{
Exception rootCause = e.GetBaseException();
return rootCause.GetType() == typeof(WebException);
}
This is not specifically related to exception handling, but a simple way to keep counters by a specific key is to use a Tuple as the key (it implements equality by value out of the box).
Note that this doesn't reset the counter on key change, it justs keeps separate counters for each key:
readonly Dictionary<Tuple<Type, string, string>, int> _counters =
new Dictionary<Tuple<Type, string, string>, int>();
bool IsCountExceeded(Exception ex)
{
// create your key with whatever properties you consider to
// be "unique"
var key = Tuple.Create(ex.GetType(), ex.StackTrace, ex.Message);
// increase counter
int counter;
if (!_counters.TryGetValue(key, out counter))
{
counter = 1;
}
else
{
counter++;
}
_counters[key] = counter;
return counter > Max;
}
You can of course always make it more readable by creating your own class, which will implement Equals/GetHashCode properly.
I am also not sure that the stack trace can be considered as a unique property, and of course, catching and ignoring exceptions is usually a bad idea.
You should specify the exception type you want to catch. Place the catch blocks in order of most specific type to most generic type.
It is not clear if the exceptions all derive from FrameworkException or if you want to use Exception, the following assumes the former.
int exceptionCount = 0;
Type lastCaughtException = null;
while(true) {
try
{
statementToExecute.Invoke();
// statement finished successfully
break;
}
catch (WebException ex)
{
if(lastCaughtException == null || lastCaughtException != ex.GetType())
exceptionCount = 0;
else
exceptionCount++;
lastCaughtException = ex.GetType();
if (exceptionCount >= MaxRetriesOnFrameworkException)
throw;
}
catch (Exception) // if you do not want to log this you can completely omit this catch
{
throw; // rethrow as it isn't a framework exception
}
}
See also try-catch (C# Reference)
This is a question about exception handling and prevention.
public static string PathCombineNoEx(string path1, string path2)
{
if (path1 == null || path2 == null /*Either validate here*/)
{
return null;
}
try
{
return System.IO.Path.Combine(path1, path2);
}
catch (ArgumentException /*or catch here*/)
{
return null;
}
}
Since exceptions are an enormous hit on performance we should try to minimize the chance for exceptions to be thrown. In the following example I've eliminated the chance that Path.Combine could throw an ArgumentnullException. This was very easy to do and does almost not affect performance in any way. However, Path.Combine also throws an ArgumentException if one of the two parameter strings contains any invalid character provided by GetInvalidPathChars.
Now, would you recommend to catch this as I did or would you really check for invalid chars before calling the Path.Combine?
What about a general recommendation that can be applied to most situations.
Maybe there is a Microsoft article about that?
Path.Combine documentation:
https://msdn.microsoft.com/de-de/library/fyy7a5kt(v=vs.110).aspx
The .NET Reference Source:
http://referencesource.microsoft.com/#mscorlib/system/io/path.cs,2d7263f86a526264
Microsft performance tip (see chapter Throw fewer exceptions):
https://msdn.microsoft.com/en-us/library/ms973839.aspx
Catching exceptions is slow since exception throwing does stack trace.
Catching exceptions is less readable; it's a kind of notorious goto: if something has happened then goto catch.
That's why I vote for validation:
if (path1 == null)
return null;
if (path2 == null)
return null;
//TODO: put other validations here, e.g. Path.GetInvalidFileNameChars()
return System.IO.Path.Combine(path1, path2);
And catch exceptions for exceptional cases only:
try {
// I can't validate this, since just after I've finished it and ready to read
// someone can
// - delete/rename the file
// - change permissions
// - lock file (e.g. start writing to it)
String data = File.ReadAllText(#"C:\MyData.txt");
...
}
catch (IOException e) {
...
}
Exceptions, as the term says, are meant to handle unexpected situations. I vote to handle foreseeable cases in code beforehand.
Exceptions can hit performance.
If it's an API,
public static string PathCombineNoEx(string path1, string path2)
{
if (String.IsNullOrWhiteSpace(path1))
{
throw new ArgumentnullException(path1);
}
//Same goes for Path2
return System.IO.Path.Combine(path1, path2);
}
Otherwise, Dmitry's answer will do.
Helpful SO posts:
Business Objects, Validation And Exceptions
Why are Exceptions said to be so bad for Input Validation?
I am downloading data from text files into db tables. The data in the files is occasionally corrupt at a field level (files are comma delimited .csv files)
I am reading each line into an object that represents the data line with properties that are the correct datatype.
If the read into the object fails due to dodgy data, I want to read the line into a similar object as the first one, only this one has all data types set to string so the read into it should not fal.
The idea being that I can create a collection of valid record objects which I will load in to the appropriate db table, and a collection of exceptions which I will load into an exceptions table. These can then be dealt with later.
So - the question:
I am going to loop through the lines of the text file and load these into the object and add the object to a collection. There will be a try/catch loop around this and if the object load fails, then in the catch section I will load the exception object and add this to the collection of exceptions.
However, what happens if the exception object load fails (for whatever reason). Do I put a try/catch around that and log exceptions - i.e a try/catch within a try/catch?
Is there a better way of doing this?
Code within a catch block is no way different to other code.
So you will have to protect every critical action with a try catch otherwise your program might crash.
2.
This might be a personal flavor, but I do not recommend to use try for control flow - do use if instead. So use if-statements to detect your dodgy data.
Yes. You can add the Try-Catch in other catch clause. It's OK.
Or as Imapler suggested, you can add the exception to a collection, and then process the collection in a loop. That's will let you process the lines with the exception later. But maybe it looks better than Try-Catch in a Catch clause.
var exceptionList = new List<ExceptionLines>();
try
{
// read lines, parse...
}
catch(Exception ex)
{
// handle the lines with the exception. Add the exception and the necessary arguments to the collection
exceptionList.Add( new ExceptionLines(....));
}
// do stuff
// handle the exceptions.
foreach(var exception in exceptionList)
{
try
{
// process the exception line.
}
catch(Exception ex)
{
// log error and handle exception
}
}
You can also wrap the exception with a wrapper. Maybe it will looks better.
// somewhere in your code...
WrapException( () =>
{
// read and parse lines...
}, (ex) =>
{
WrapException(ex, ParseToExceptionFunction, HandleExceptionParseFunction, false);
}, false);
void WrapException(Action func, Action<Exception> handleCatch, bool rethrow)
{
try
{
func();
}
catch(Exception ex)
{
handleCatch(ex);
if (rethrow)
throw;
}
}
static void WrapException<T>(T arg, Action<T> func, Action<Exception> handleCatch, bool rethrow)
{
try
{
func(arg);
}
catch (Exception ex)
{
handleCatch(ex);
if (rethrow)
throw;
}
}
void ParseToExceptionFunction(ArgType arg)
{
// try to parse to excetion
}
void HandleExceptionParseFunction(Exception ex)
{
// handle the exception for parsing the line with the exception
}
You can also implement the ParseToExceptionFunction and the HandleExceptionParseFunction as lambdas...
So I used everybody's advice.
Used if than else's to catch dodgy data, created a list of good data and a list of exceptions (raised by the if and else's) and then processed the lists in try / catches to catch any other exceptions that may arile (ref integrity issues etc)
Thanks for the advice.
Modifying to make it clear:
I have a question on exception logging and graceful exit. This is in continuation with previous question. The code looks like:
string status = "0";
ClassA ObjA = new ClassA();
try
{
status = objA.Method1();
if (status != "-1")
{
status = objA.Method1();
}
}
catch (Exception Ex)
{
//Log Exception EX
}
Inside the Method1:
public string Method1()
{
string status = "0";
try
{
//Code
return "0";
}
catch (Exception Ex)
{
//Log Exception with details
return "-1"
}
}
I log the Exception in the calling method and return only a status to the caller.
Should I return the Exception to the calling method or is only a status sufficient. With a status of "-1", I know there was an Exception in the called method and details of that Exception were logged in a log file.
I think it is OK to do it like that if you have a lot of status codes, otherwise you could also just throw an exception and catch it in the method higher up.
Also maybe reconsider your return type. Looks like you could be using integers, think you are opening yourself up to errors using strings.
Don't use the status return value, it is not adding anything that is useful to you.
consider,
var a = new ClassA()
try
{
a.Mehtod1();
}
catch
{
try
{
a.Method1();
}
catch (Exception ex)
{
//Log without details;
}
}
class ClassA
{
void Method1()
{
try
{
//Code
}
catch (Exception ex)
{
//Log with details
throw;
}
}
}
This code achieves the same functionality but leaves the return code of the functions for something useful and non exceptional.
More generally, I suggest that you should have one catch all handler at the top level of your application that deals with logging, or at most one per public entry point. Other handlers should deal with specific exception types that they can actually "handle" (do something about.)
It all depends on the purpose and implementation of the code; sometimes it is better to allow exceptions to pass back to the caller - they should be used in exceptional cases.
If you do intend on using return codes, however, I would be more inclined to use enum's (though, again, it depends what the purpose of the code is). That way, it is easy for the caller to check against an available selection of return codes. Also, a comment on using integers or strings as error codes - it may not be very descriptive for a caller to know what the issue was. In this case, throwing an Exception or a specific type (containing the error message), or returning a pre-defined enum with a descriptive name, would be more meaningful to the caller.
From these short code snippets which does nothing it is very difficult to say what is best practice.
In general it is best to push exceptions to where they are handled best. If you are writing a framework for interfacing with some webservice the users of your framework will most likely not care about network exceptions etc. - they want return codes or, even better some framework specific exceptions that you include/code.
Hm - in your situation I'd rather do the following, but it really depends on the situation:
public string Method1()
{
string status = "0";
//Code - Exception may be thrown
return "0";
}
string status = "0";
ClassA ObjA = new ClassA();
try
{
status = objA.Method1();
}
Catch(Exception Ex)
{
//Log Exception EX
status = "-1;
}
EDIT
Sometimes it's hard to define values that indicate whether an error occurred in the method. You should keep Nullable types in mind. If you can find a suitable return value that indicates errors, it may also be ok to log the error within the method that caused the error and just react to the return value as you suggested.
By the way: In your code you're calling Method1 twice if the first call succeeded. I guess that is because it is a quick sample...
class MyException : Exception
{
public readonly int status;
public MyException(int status, string msg):base(msg)
{
this.status = status;
}
}
public string Method1()
{
throw new MyException(-1,"msg");
return "0";
}
SomeCode()
{
try
{
Method1();
}catch(MyException ex)
{
ex.status //here you get the status
}
}
Situation:
My application need to process the first step in the business rules (the initial try-catch statement). If an certain error occurs when the process calls the helper method during the step, I need to switch to a second process in the catch statement. The back up process uses the same helper method. If an same error occurs during the second process, I need to stop the entire process and throw the exception.
Implementation:
I was going to insert another try-catch statement into the catch statement of the first try-catch statement.
//run initial process
try
{
//initial information used in helper method
string s1 = "value 1";
//call helper method
HelperMethod(s1);
}
catch(Exception e1)
{
//backup information if first process generates an exception in the helper method
string s2 = "value 2";
//try catch statement for second process.
try
{
HelperMethod(s2);
}
catch(Exception e2)
{
throw e2;
}
}
What would be the correct design pattern to avoid code smells in this implementation?
I caused some confusion and left out that when the first process fails and switches to the second process, it will send different information to the helper method. I have updated the scenario to reflect the entire process.
If the HelperMethod needs a second try, there is nothing directly wrong with this, but your code in the catch tries to do way too much, and it destroys the stacktrace from e2.
You only need:
try
{
//call helper method
HelperMethod();
}
catch(Exception e1)
{
// maybe log e1, it is getting lost here
HelperMethod();
}
I wouldn't say it is bad, although I'd almost certainly refactor the second block of code into a second method, so keep it comprehensible. And probably catch something more specific than Exception. A second try is sometimes necessary, especially for things like Dispose() implementations that might themselves throw (WCF, I'm looking at you).
The general idea putting a try-catch inside the catch of a parent try-catch doesn't seem like a code-smell to me. I can think of other legitimate reasons for doing this - for instance, when cleaning up an operation that failed where you do not want to ever throw another error (such as if the clean-up operation also fails). Your implementation, however, raises two questions for me: 1) Wim's comment, and 2) do you really want to entirely disregard why the operation originally failed (the e1 Exception)? Whether the second process succeeds or fails, your code does nothing with the original exception.
Generally speaking, this isn't a problem, and it isn't a code smell that I know of.
With that said, you may want to look at handling the error within your first helper method instead of just throwing it (and, thus, handling the call to the second helper method in there). That's only if it makes sense, but it is a possible change.
Yes, a more general pattern is have the basic method include an overload that accepts an int attempt parameter, and then conditionally call itself recursively.
private void MyMethod (parameterList)
{ MyMethod(ParameterList, 0)l }
private void MyMethod(ParameterList, int attempt)
{
try { HelperMethod(); }
catch(SomeSpecificException)
{
if (attempt < MAXATTEMPTS)
MyMethod(ParameterList, ++attempt);
else throw;
}
}
It shouldn't be that bad. Just document clearly why you're doing it, and most DEFINITELY try catching a more specific Exception type.
If you need some retry mechanism, which it looks like, you may want to explore different techniques, looping with delays etc.
It would be a little clearer if you called a different function in the catch so that a reader doesn't think you're just retrying the same function, as is, over again. If there's state happening that's not being shown in your example, you should document it carefully, at a minimum.
You also shouldn't throw e2; like that: you should simply throw; if you're going to work with the exception you caught at all. If not, you shouldn't try/catch.
Where you do not reference e1, you should simply catch (Exception) or better still catch (YourSpecificException)
If you're doing this to try and recover from some sort of transient error, then you need to be careful about how you implement this.
For example, in an environment where you're using SQL Server Mirroring, it's possible that the server you're connected to may stop being the master mid-connection.
In that scenario, it may be valid for your application to try and reconnect, and re-execute any statements on the new master - rather than sending an error back to the caller immediately.
You need to be careful to ensure that the methods you're calling don't have their own automatic retry mechanism, and that your callers are aware there is an automatic retry built into your method. Failing to ensure this can result in scenarios where you cause a flood of retry attempts, overloading shared resources (such as Database servers).
You should also ensure you're catching exceptions specific to the transient error you're trying to retry. So, in the example I gave, SqlException, and then examining to see if the error was that the SQL connection failed because the host was no longer the master.
If you need to retry more than once, consider placing an 'automatic backoff' retry delay - the first failure is retried immediately, the second after a delay of (say) 1 second, then doubled up to a maximum of (say) 90 seconds. This should help prevent overloading resources.
I would also suggest restructuring your method so that you don't have an inner-try/catch.
For example:
bool helper_success = false;
bool automatic_retry = false;
//run initial process
try
{
//call helper method
HelperMethod();
helper_success = true;
}
catch(Exception e)
{
// check if e is a transient exception. If so, set automatic_retry = true
}
if (automatic_retry)
{ //try catch statement for second process.
try
{
HelperMethod();
}
catch(Exception e)
{
throw;
}
}
Here's another pattern:
// set up state for first attempt
if(!HelperMethod(false)) {
// set up state for second attempt
HelperMethod(true);
// no need to try catch since you're just throwing anyway
}
Here, HelperMethod is
bool HelperMethod(bool throwOnFailure)
and the return value indicates whether or not success occurred (i.e., false indicates failure and true indicates success). You could also do:
// could wrap in try/catch
HelperMethod(2, stateChanger);
where HelperMethod is
void HelperMethod(int numberOfTries, StateChanger[] stateChanger)
where numberOfTries indicates the number of times to try before throwing an exception and StateChanger[] is an array of delegates that will change the state for you between calls (i.e., stateChanger[0] is called before the first attempt, stateChanger[1] is called before the second attempt, etc.)
This last option indicates that you might have a smelly setup though. It looks like the class that is encapsulating this process is responsible for both keeping track of state (which employee to look up) as well as looking up the employee (HelperMethod). By SRP, these should be separate.
Of course, you need to a catch a more specific exception than you currently are (don't catch the base class Exception!) and you should just throw instead of throw e if you need to rethrow the exception after logging, cleanup, etc.
You could emulate C#'s TryParse method signatures:
class Program
{
static void Main(string[] args)
{
Exception ex;
Console.WriteLine("trying 'ex'");
if (TryHelper("ex", out ex))
{
Console.WriteLine("'ex' worked");
}
else
{
Console.WriteLine("'ex' failed: " + ex.Message);
Console.WriteLine("trying 'test'");
if (TryHelper("test", out ex))
{
Console.WriteLine("'test' worked");
}
else
{
Console.WriteLine("'test' failed: " + ex.Message);
throw ex;
}
}
}
private static bool TryHelper(string s, out Exception result)
{
try
{
HelperMethod(s);
result = null;
return true;
}
catch (Exception ex)
{
// log here to preserve stack trace
result = ex;
return false;
}
}
private static void HelperMethod(string s)
{
if (s.Equals("ex"))
{
throw new Exception("s can be anything except 'ex'");
}
}
}
Another way is to flatten the try/catch blocks, useful if you're using some exception-happy API:
public void Foo()
{
try
{
HelperMethod("value 1");
return; // finished
}
catch (Exception e)
{
// possibly log exception
}
try
{
HelperMethod("value 2");
return; // finished
}
catch (Exception e)
{
// possibly log exception
}
// ... more here if needed
}
An option for retry (that most people will probably flame) would be to use a goto. C# doesn't have filtered exceptions but this could be used in a similar manner.
const int MAX_RETRY = 3;
public static void DoWork()
{
//Do Something
}
public static void DoWorkWithRetry()
{
var #try = 0;
retry:
try
{
DoWork();
}
catch (Exception)
{
#try++;
if (#try < MAX_RETRY)
goto retry;
throw;
}
}
In this case you know this "exception" probably will happen so I would prefer a simple approach an leave exceptions for the unknown events.
//run initial process
try
{
//initial information used in helper method
string s1 = "value 1";
//call helper method
if(!HelperMethod(s1))
{
//backup information if first process generates an exception in the helper method
string s2 = "value 2";
if(!HelperMethod(s2))
{
return ErrorOfSomeKind;
}
}
return Ok;
}
catch(ApplicationException ex)
{
throw;
}
I know that I've done the above nested try catch recently to handle decoding data where two third party libraries throw exceptions on failure to decode (Try json decode, then try base64 decode), but my preference is to have functions return a value which can be checked.
I generally only use the throwing of exceptions to exit early and notify something up the chain about the error if it's fatal to the process.
If a function is unable to provide a meaningful response, that is not typically a fatal problem (Unlike bad input data).
It seems like the main risk in nested try catch is that you also end up catching all the other (maybe important) exceptions that might occur.