C# - Handle BulkInsert when exception occurs? - c#

I have code like so:
public void InsertData() {
...
try {
context.BulkInsert(Table1Data);
context.BulkInsert(Table2Data);
context.BulkInsert(Table3Data);
context.BulkInsert(Table4Data);
}
catch (Exception ex) {
Console.WriteLine("Data failed to insert");
}
}
Let's say that an exception occurs on the insert of "Table2Data". If so, then the database has already inserted "Table1Data" but because of the exception now won't insert "Table3Data" or "Table4Data".
Regardless of "Table2Data" working or not, I need "Table3Data" and "Table4Data" inserted.
What would be the best way to handle this? Can I add something like a goto statement in my exception so that it will continue on with the inserts? I am mainly hoping to avoid putting each BulkInsert into its own try catch.

Why not have a code like so:
public void InsertData() {
...
foreach(var x in new[]{Table1Data,Table2Data,Table3Data,Table4Data})
try {
context.BulkInsert(x);
}
catch {
Console.WriteLine("Data failed to insert");
}
}

You can probably pass tabledata(s) from outside as a parameter, or use a finally block in which based on an if condition of your try code fail/pass, make recursive calls?

Related

How can I tell my method to ignore an exception and continue running?

how can I prevent an error in one part of my controller method from causing the whole method from returning a 500 error?
I have this controller method that should delete a row in my database:
// DELETE: api/FaunaLists/5
[HttpDelete("{id}")]
public async Task<ActionResult<FaunaList>> DeleteFaunaList(string id)
{
// delete any associated references in FaunaList_EcosystemList table
// if that table doesn't have any references, this whole method throws a 500 error :(
if (faunaList.EcosystemId != null)
{
faunaEcosystemRef = _context.FaunaList_EcosystemList.Where(x => x.EcosystemId == faunaList.EcosystemId).ToList();
_context.FaunaList_EcosystemList.RemoveRange(faunaEcosystemRef);
}
try
{
_context.FaunaList.Remove(faunaList);
await _context.SaveChangesAsync();
}
catch (Exception e)
{
Message = _loggingMessage.GetLogException(this.GetType().Name.ToString(), ControllerActions.Exception, "FaunaList DELETE", id.ToString(), e.InnerException.ToString());
_logger.LogCritical(Message);
return BadRequest("Error when saving database changes. See error details.");
}
return faunaList;
}
In the method, you can see I check for an Id called faunaList.EcosystemId.
If that exists, then I try to delete it.
However, if the EcosystemId doesn't exist in the FaunaList_EcosystemList table, it throws this error in the browser:
DELETE https://sci-measure.xyz.gov/api/FaunaLists/TTE37B02-7624-4ED5-B62D-B7832C0D7E60 net::ERR_FAILED 500
How can I ignore that error and just let the rest of the method continue to execute?
Thanks!
When you write try-catch block like so:
try{
//your code here
}
catch(Exception){
//your code here
}
It will catch every exception.
If you only want to catch one certain exception, you can specify that in the catch like so:
try{
// your code here
}
catch(SpecificException){
// your code here
}
This code will catch the specific exception and ignore others.
Or you can create a try-catch block for the if statement and write the continue keyword and it will continue with the code.

Continue statement outside foreach loop block

With C# can we use continue outside foreach? I mean can we skip exception scenarios and move to next record validation ? As per my scenario, I have to refactor code to a separate method instead of using continue in the foreach loop.
foreach (var name in Students)
{
//forloop should continue even if there is any logic exception and move to next record
CheckIfStudentExist();
}
private void CheckIfStudentExist()
{
try
{
//do some logic to verify if student exist & take to catch if there is some error in logic
}
Catch(Exception)
{
continue;
}
}
You can't write continue statement outside loop block.
If you want exception to be silent, just leave catch block empty.
private void CheckIfStudentExist()
{
try
{
//do some logic to verify if student exist & take to catch if there is some error in logic
}
catch
{
}
}
However, empty catch block is a bad practice. At least write some log statement inside so the exception is not lost forever.
It's better to declare our own business exception class so we can catch specific exception type and leave other type (possibly fatal) of exceptions to halt our code execution.
private void CheckIfStudentExist()
{
try
{
//do some logic to verify if student exist & take to catch if there is some error in logic
}
catch(ValidationException e)
{
// example of the log statement. Change accordingly.
Log.Error(e, "Validation failed when validating student Id {0}", studentId);
}
}

Exception handling - Exception within a catch clause?

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.

C# try catch continue execution

I have a question that might seem fairly simple (of course if you know the answer).
A certain function I have calls another function but I want to continue execution from the caller even though the callee has thrown an exception. Let me give you an example:
something function1()
{
try
{
//some code
int idNumber = function2();
//other code that need to execute even if function2 fails
return something;
}
catch(Exception e)
{//... perhaps something here}
}
EDIT: function1 also has a return statement so nothing can in fact crash on the way
In function2 I need to do stuff but I only need to log if anything fails, example:
int function2()
{
try
{
//dostuff
}
catch(Exception e)
{
//Log stuff to db
}
}
ok, now my question is, what should I do if I wanted to continue execution in function1 even if function 2 throws an error?
Sometimes I mix up if I should do throw; or throw e; or throw nothing at all (leave catch block empty)
Leaving the catch block empty should do the trick. This is almost always a bad idea, though. On one hand, there's a performance penalty, and on the other (and this is more important), you always want to know when there's an error.
I would guess that the "callee" function failing, in your case, is actually not necessarily an "error," so to speak. That is, it is expected for it to fail sometimes. If this is the case, there is almost always a better way to handle it than using exceptions.
There are, if you'll pardon the pun, exceptions to the "rule", though. For example, if function2 were to call a web service whose results aren't really necessary for your page, this kind of pattern might be ok. Although, in almost 100% of cases, you should at least be logging it somewhere. In this scenario I'd log it in a finally block and report whether or not the service returned. Remember that data like that which may not be valuable to you now can become valuable later!
Last edit (probably):
In a comment I suggested you put the try/catch inside function2. Just thought I would elaborate. Function2 would look like this:
public Something? function2()
{
try
{
//all of your function goes here
return anActualObjectOfTypeSomething;
}
catch(Exception ex)
{
//logging goes here
return null;
}
}
That way, since you use a nullable return type, returning null doesn't hurt you.
Why cant you use the finally block?
Like
try {
} catch (Exception e) {
// THIS WILL EXECUTE IF THERE IS AN EXCEPTION IS THROWN IN THE TRY BLOCK
} finally {
// THIS WILL EXECUTE IRRESPECTIVE OF WHETHER AN EXCEPTION IS THROWN WITHIN THE TRY CATCH OR NOT
}
EDIT after question amended:
You can do:
int? returnFromFunction2 = null;
try {
returnFromFunction2 = function2();
return returnFromFunction2.value;
} catch (Exception e) {
// THIS WILL EXECUTE IF THERE IS AN EXCEPTION IS THROWN IN THE TRY BLOCK
} finally {
if (returnFromFunction2.HasValue) { // do something with value }
// THIS WILL EXECUTE IRRESPECTIVE OF WHETHER AN EXCEPTION IS THROWN WITHIN THE TRY CATCH OR NOT
}
Or you can encapsulate the looping logic itself in a try catch e.g.
for(int i = function2(); i < 100 /*where 100 is the end or another function call to get the end*/; i = function2()){
try{
//ToDo
}
catch { continue; }
}
Or...
try{
for(int i = function2(); ; ;) {
try { i = function2(); return; }
finally { /*decide to break or not :P*/continue; } }
} catch { /*failed on first try*/ } finally{ /*afterwardz*/ }
just do this
try
{
//some code
try
{
int idNumber = function2();
}
finally
{
do stuff here....
}
}
catch(Exception e)
{//... perhaps something here}
For all intents and purposes the finally block will always execute. Now there are a couple of exceptions where it won't actually execute: task killing the program, and there is a fast fail security exception which kills the application instantly. Other than that, an exception will be thrown in function 2, the finally block will execute the needed code and then catch the exception in the outer catch block.
Do you mean you want to execute code in function1 regardless of whether function2 threw an exception or not? Have you looked at the finally-block? http://msdn.microsoft.com/en-us/library/zwc8s4fz.aspx
In your second function remove the e variable in the catch block then add throw.
This will carry over the generated exception the the final function and output it.
Its very common when you dont want your business logic code to throw exception but your UI.

Ignore a Specific Typed Exception

I would like to ignore a specific Type of exception in a group of statements; without having to put empty Try..Catches around them.
try{ o1.Update(); } catch (Exceptions.NoChangeMade ex) {}
try{ o2.Update(); } catch (Exceptions.NoChangeMade ex) {}
try{ o3.Update(); } catch (Exceptions.NoChangeMade ex) {}
I would like either a On Error Resume type way, or a Continue way within the catch
Here's a simple way:
ExecuteIgnore(o1.Update);
ExecuteIgnore(o2.Update);
ExecuteIgnore(o3.Update);
...
private static void ExecuteIgnore(Action action)
{
try { action(); }
catch(Exceptions.NoChangeMade) { }
}
You can make it even more generic (if a bit longer) like this:
ExecuteIgnore<Exceptions.NoChangeMade>(o1.Update);
ExecuteIgnore<Exceptions.NoChangeMade>(o2.Update);
ExecuteIgnore<Exceptions.NoChangeMade>(o3.Update);
...
public static void ExecuteIgnore<T>(Action action) where T : Exception
{
try { action(); }
catch(T) { }
}
If you want them all to update, you don't really have a choice without wrapping the exception.
You could do something like:
var list = List<objects_to_update> ();
list.Add(o1);
list.Add(o2);
etc.
list.ForEach(x=>
try{list.Update()}
catch{}
);
You'll still have to wrap them in an exception, but at least this way you're only writing it once.
Are these o1, o2, o3 objects related? Could you put them in a collection or an array?
If you do this, you could modify your code to use a loop to update the items and then you could have the empty catch block effectively pass control on to the next iteration of the loop.
Some pseudocode to illustrate:
foreach(DataTypeOfO o in CollectionOfOs)
{
try
{
o.Update();
}
catch(Exceptions.NoChangeMade ex)
{ }
}
If o1/o2/o3 are all the same class then put 1 try catch in the .Update() method to catch the specific exception that you are looking for. Or better yet, change the code so that it does not throw the exception at all.

Categories

Resources