exception gets handled by the outermost try/catch. windows services - c#

Function that throws the ThirdPartyException (I don't know how does their code work) exception:
private void RequestDocuments(/* arguments... */) {
while(true) {
var revision = lastRevision;
var fetchedDocuments = 0;
try {
foreach(var document in connection.QueryDocuments(revision)) {
if(fetchedDocuments > fetchQuota) return;
container.Add(document);
++fetchedDocuments;
Logger.Log.InfoFormat("added document (revision: {0}) into inner container", document.Revision);
}
Logger.Log.Info("Done importing documents into the inner container");
return;
}
catch(Exception ex) {
if(ex is ThirdPartyException) {
// handle this in a certain way!
continue;
}
}
}
}
this function is called inside a worker thread like this:
private void ImportDocuments() {
while(!this.finishedEvent.WaitOne(0, false)) {
try {
var documents = new List<GohubDocument>();
RequestDocuments(remoteServerConnection, documents, lastRevision, 100);
}
catch(Exception ex) {
// here is where it really gets handled!!!?
}
}
}
the exception is handled only in the outermost (which is inside the ImportDocuments method) try/catch.
Why is that?

If that's a LINQ API which exposes IQueryable you don't get an error due to the deferred execution that LINQ to SQL implementations typically uses.
To prevent it you have to invoke .ToList(), FirstOrDefault() etc within your first method. That makes sure that the query really have been executed against your data source.
Solution:
var documents = connection.QueryDocuments(revision).ToList();
foreach(var document in documents) {
if(fetchedDocuments > fetchQuota) return;
// [...]
}

Related

Try-Catch within Using()

My code is currently
using(var driver = new driver()){something}
And I want to be able to catch exceptions. However I only want to catch exceptions thrown by "driver = new driver". Looking online I can find how to catch exceptions thrown by the whole thing or by "something" but I cannot work out how to put a try-catch into the "using" parameter.
It's a very strange requirement, but whatever that's your call.
You should get rid of the using completely, and handle the dispose yourself (which has the same result).
This is what you want:
driver driver = null;
try
{
try
{
driver = new driver();
}
catch(Exception ex)
{
// Here is your specific exception.
}
// Do something
}
finally
{
if(driver != null)
driver.Dispose();
}
Just do it:
Driver driver = null;
try
{
driver = new Driver();
}
catch()
{
// do whatever, throw, fail, return...
}
// if you did not break out of your logic in the catch (why not?)
// add an if(driver != null) before you proceed
using(driver)
{
// something
}
You can add a method to construct your driver and put your try/catch in there:
private static Driver CreateDriver()
{
try
{
return new Driver();
}
catch(Exception ex)
{
// whatever other exception handling you want
return null;
}
}
using(var driver = CreateDriver())
{
// something
}
Of course, if you do this, when your something code is executing inside the using block, driver may be null, so you'll need to check for this, e.g.:
using(var driver = CreateDriver())
{
if (driver != null)
{
// something
}
}
The "using" clause, primarily function is to dispose managed code resources once the process inside the clause has been completed. It "hides" a try catch block inside it, but if you really want to handle errors, you need to do it yourself.
eg.
Try
{
//do stuff
}
catch (exception ex)
{
//handle exception
//resource.Dispose();
}
After you handle your exceptions, you should dispose the unused resources by calling .Dispose(), assuming that the latter is a managed code resource and encapsulates the IDisposable interface

Retrieve triggering an update in plugin

I've got a plugin on Update (pre-op) of InvoiceDetail, in which I'm retrieving the associated Invoice to get some more information from it (ie: the tax profile that was selected at the invoice level) in CRM 2016.
Here's how I do it:
//xrmObjects is an object containing all useful objects in plugins/workflow...
var invoice = RetrieveEntity(xrmObjects.Service, xrmObjects.TracingService, image["invoiceid"] as EntityReference, new ColumnSet("invoiceid", "pricelevelid", "customerid", "opportunityid", "xtc_tax_definition"));
This specific line of code above triggers another Update on InvoiceDetail
Here's the method invoked above:
public static Entity RetrieveEntity(IOrganizationService service, ITracingService tracingService, EntityReference target, ColumnSet columnSet)
{
Entity entity = new Entity();
try
{
entity = CrmServiceExtensions.ExecuteWithRetry<RetrieveResponse>(service, new RetrieveRequest
{
Target = target,
ColumnSet = columnSet
}).Entity;
}
catch (Exception ex)
{
tracingService.Trace($"Error retrieving {target.LogicalName}: {ex.Message}");
throw;
}
return entity;
}
Here's ExecuteWithRetry:
public static T ExecuteWithRetry<T>(IOrganizationService service, OrganizationRequest request)
where T : OrganizationResponse
{
T response = null;
int i = 0;
// Maximum of five iterations.
while (i < 5)
{
try
{
response = (T)service.Execute(request);
// If the Execute does not throw an Exception, break the loop
break;
}
catch (System.Web.Services.Protocols.SoapException e)
{
// Retry if the SoapException is a "Generic SQL Error",
// otherwise rethrow the SoapException.
// "Generic SQL Error" might indicate a deadlock.
if (e.Detail.InnerText.ToLower().Contains("generic sql error"))
{
++i;
// Wait (sleep thread) for i * 1000 milliseconds.
// So, first iteration waits 1 second,
// while fifth iteration will wait 5 seconds.
System.Threading.Thread.Sleep(i * 1000);
}
else throw;
}
}
if (i >= 5)
{
throw new Exception("ExecuteWithRetry: too many retries");
}
return response;
}
I have validated that nothing funky is happening, the update message on InvoiceDetail is triggered again at the line response = (T)service.Execute(request);
I also tried by using early-bound and a context to retrieve the invoice but the LoadProperty methods which loads the invoice does the same thing....
using (XrmServiceContext ctx = new XrmServiceContext(xrmObjects.Service))
{
Xrm.InvoiceDetail image = xrmObjects.PluginContext.PreEntityImages["invoicedetail"].ToEntity<Xrm.InvoiceDetail>();
try
{
ctx.LoadProperty(image, "invoice_details");
}
catch (Exception ex)
{
throw new InvalidPluginExecutionException($"Error retrieving invoice details' invoice: {ex.Message}");
}
}
I can't see anything in my steps configuration that would do this. Any ideas?
Instead of using LoadProperty, I simply retrieved the invoice manually like so
var invoice = ctx.InvoiceSet.SingleOrDefault(x => x.Id == image.InvoiceId.Id);
Instead of:
ctx.LoadProperty(image, "invoice_details");
For some reason, LoadProperty is triggering unwanted update message on child invoice details...

Output exception messages including all inners with LINQ

Is it possible to output all error messages of thrown exception including inners via LINQ?
I implemented the functionality without LINQ, but I would like to have more concise code.
(Isn't the purpose of the LINQ?)
My code without LINQ follows:
try {
...
} catch (Exception ex) {
string msg = "Exception thrown with message(s): ";
Exception curEx= ex;
do {
msg += string.Format("\n {0}", curEx.Message);
curEx = curEx.InnerException;
} while (curEx != null);
MessageBox.Show(msg);
}
Linq works on sequences, ie., collections of objects. The exception.InnerException hierarchy is instead nested instances of single objects. What you are doing algorithmically is not inherently a sequence operation, and would not be covered by Linq approaches.
You could define a method that explores the hierarchy and returns (yields) a sequence of objects as they are found, but this ultimately is going to be the same algorithm you're currently using to explore the depths, although you could then choose to apply a sequence operation (Linq) on the results.
To follow up on #Anthony Pegram's answer, you could define an extension method to get a sequence of the inner exceptions:
public static class ExceptionExtensions
{
public static IEnumerable<Exception> GetAllExceptions(this Exception ex)
{
List<Exception> exceptions = new List<Exception>() {ex};
Exception currentEx = ex;
while (currentEx.InnerException != null)
{
currentEx = currentEx.InnerException;
exceptions.Add(currentEx);
}
return exceptions;
}
}
then you would be able to use LINQ on the sequence. If we have a method that throws nested exceptions like this:
public static class ExceptionThrower {
public static void ThisThrows() {
throw new Exception("ThisThrows");
}
public static void ThisRethrows() {
try {
ExceptionThrower.ThisThrows();
}
catch (Exception ex) {
throw new Exception("ThisRetrows",ex);
}
}
}
here's how you can use LINQ with the little extension method we created:
try {
ExceptionThrower.ThisRethrows();
}
catch(Exception ex) {
// using LINQ to print all the nested Exception Messages
// separated by commas
var s = ex.GetAllExceptions()
.Select(e => e.Message)
.Aggregate((m1, m2) => m1 + ", " + m2);
Console.WriteLine(s);
}
In the current .NET Framework, this is now possible:
string RecursiveStackTrace(Exception ex)
=> $"{ex.Message}<br />{ex.StackTrace}{((ex.InnerException != null) ? $"<br /><br />{RecursiveStackTrace(ex.InnerException)}" : string.Empty)}";

C# - Proceed with foreach() loop if an error occurs

I currently have a listview and a folder full of XML documents. I am using a foreach() loop to go through all the XML files and load data into the listview accordingly. My question is, how do I carry on with the foreach() loop if there is an error within in (example: if one of the XML files is not completely valid, contains errors, etc) and still add the data to the listview? I'm not asking how to parse the XML or how to load it into the listview, that much I know how to do, just not how to proceed with the loop if an error occurs.
Do you want:
foreach(var xml in xmls)
{
try
{
//import xml to listview
}
catch (SomeException e)
{
//deal with the exception here
}
}
Wrap the inner contents of the loop in a try ... catch block.
e.g.
foreach (var foo in iterableThing) {
try {
DoStuff(foo);
}
catch (AppropriateException) {
// Handle the exception (or ignore it)...
}
catch (SomeOtherException) {
// Handle the exception (or ignore it)...
}
}
wouldnt you do
foreach( loop )
{
try {
}
catch (Exception ex)
{
// all errors caught here, but the loop would continue
}
}
You can do the file processing in a try catch block and handle the error condition. You can handle the errors gracefully in catch and continue with loading of data.
I think you should do this:
foreach(var doc in docs)
{
//Make a function to evaluate the doc
if(isValid(doc))
{
//Logging or something
continue;
}
//Add data to listview
}
If your processing code throws exceptions, then use a try/catch block. If you're checking the results of some method with an if block, then use continue.
If you need to use this more often or if you just want to have more elegant code, you can use lambda expressions and delegates to create a new abstraction for this purpose:
static void SafeForEach<T>(this IEnumerable<T> source, Action<T> op) {
foreach(var el in source) {
try { op(el); }
catch (Exception e) { }
}
}
Then you can write just:
xmls.SafeForEach(xml => {
// Xml processing
});
However, using exceptions in situations where an error is expected is not the best programming style. If you can write a method, say IsValid that returns true if the document is valid, then you could write:
foreach(var xml in xmls.Where(x => x.IsValid)) {
// Xml processing
}

C#: Equivalent of the python try/catch/else block

In Python, there is this useful exception handling code:
try:
# Code that could raise an exception
except Exception:
# Exception handling
else:
# Code to execute if the try block DID NOT fail
I think it's useful to be able to separate the code that could raise and exception from your normal code. In Python, this was possible as shown above, however I can't find anything like it in C#.
Assuming the feature or one like it doesn't exist, is it standard practice to put normal code in the try block or after the catch block?
The reason I ask is because I have the following code:
if (!IsReadOnly)
{
T newobj;
try
{
newobj = DataPortal.Update<T>(this);
List<string> keys = new List<string>(BasicProperties.Keys);
foreach (string key in keys)
{
BasicProperties[key] = newobj.BasicProperties[key];
}
}
catch (DataPortalException)
{
// TODO: Implement DataPortal.Update<T>() recovery mechanism
}
}
Which requires the normal code to be in the try block because otherwise if an exception was raised and subsequently handled, newobj would be unassigned, but it feels quite unnatural to have this much code in the try block which is unrelated to the DataPortalException. What to do?
Thanks
I would prefer to see the rest of the code outside the try/catch so it is clear where the exception you are trying to catch is coming from and that you don't accidentally catch an exception that you weren't trying to catch.
I think the closest equivalent to the Python try/catch/else is to use a local boolean variable to remember whether or not an exception was thrown.
bool success;
try
{
foo();
success = true;
}
catch (MyException)
{
recover();
success = false;
}
if (success)
{
bar();
}
But if you are doing this, I'd ask why you don't either fully recover from the exception so that you can continue as if there had been success, or else fully abort by returning an error code or even just letting the exception propagate to the caller.
Barbaric solution: create an Else class derived from Exception, throw an instance of it at the end of the try block, and use catch (Else) {...} to handle the other stuff.
I feel so dirty.
This will might get downvoted but doesn't c# have goto(note I have almost no c# knowledge so I have no idea if this works).
what about something like
try
{
...
}
catch(Exception ex)
{
...
goto Jump_past_tryelse
}
...//Code to execute if the try block DID NOT fail
Jump_past_tryelse:
...
C# does not have such a concept, so you are just left with three options,
put the else code inside the try.
put the else code outside the try catch block, use a local variable to indicate success or failure, and an if block around your else code.
put the else code in the finally block, use a local variable to indicate success or failure, and an if block arount you else code.
Allow me to repeat an idea from a similar StackOverflow question. You cannot do this directly, but you can write a method that encapsulates the behavior you need. Look at the original question to see how to implement the method (if you're not familiar with lambda expressions and Func delegates). The usage could look like this:
TryExceptRaise(() => {
// code that can throw exception
}, (Exception e) => {
// code to run in case of an exception
return (...);
}, () => {
// code to run if there is no exception
return (...);
});
Just put your "else" block before the catch. Then, it will only execute if code execution reaches that point:
try
{
fee();
fi();
foe();
fum();
/// put your "else" stuff here.
/// It will only be executed if fee-fi-foe-fum did not fail.
}
catch(Exception e)
{
// handle exception
}
Given that, I fail to see the use of try..catch...else unless there's something vital missing from the OP's description.
With C# version 7, you could use local functions to emulate this behaviour:
Example 1: (since C# version 7)
void Main()
{
void checkedCode()
{
try
{
foo();
}
catch (Exception ex)
{
recover();
return;
}
// ElseCode here
}
checkedCode();
}
If you prefer lambda syntax, you could also declare a run method
void Run(Action r) { r(); }
which only needs to be there once in your code, and then use the pattern for anonymous methods as follows
Example 2: (older C# versions and C# version 7)
Run(() => {
try
{
foo();
}
catch (Exception)
{
recover();
return;
}
// ElseCode here
});
whereever you need to enclose code in a safe context.
Try it in DotNetFiddle
Notes:
In both examples a function context is created so that we can use return; to exit on error.
You can find a similar pattern like the one used in Example 2 in JavaScript: Self-invoking anonymous functions (e.g. JQuery uses them). Because in C# you cannot self-invoke, the helper method Run is used.
Since Run does not have to be a local function, Example 2 works with older C# versions as well
You could do something like this:
if (!IsReadOnly)
{
T newobj = null;
try
{
newobj = DataPortal.Update<T>(this);
}
catch (DataPortalException)
{
// TODO: Implement DataPortal.Update<T>() recovery mechanism
}
if (newobj != null)
{
List<string> keys = new List<string>(BasicProperties.Keys);
foreach (string key in keys)
{
BasicProperties[key] = newobj.BasicProperties[key];
}
}
}
that would be the empty statement like hits
try
{
somethingThatCanThrow();
}
catch(Exception ex)
{
LogException(ex);
return;
}
ContinueFlow();
if (!IsReadOnly)
{
T newobj;
bool Done;
try
{
newobj = DataPortal.Update<T>(this);
List<string> keys = new List<string>(BasicProperties.Keys);
foreach (string key in keys)
{
BasicProperties[key] = newobj.BasicProperties[key];
}
Done = true;
}
catch (DataPortalException)
{
// TODO: Implement DataPortal.Update<T>() recovery mechanism
Done = false;
}
finally
{
if (newobj != null && Done == false)
{
List<string> keys = new List<string>(BasicProperties.Keys);
foreach (string key in keys)
{
BasicProperties[key] = newobj.BasicProperties[key];
}
}
}
}

Categories