I am running this piece of code in my application.
public Task<BulkResponse<JObject>> GetRelatedObjectsAsync(IEnumerable<PrimaryObjectInfo> primaryObjectInfos)
{
var allSecondaries = new List<Tuple<int, List<JObject>>>();
var exceptionsDict = new ConcurrentDictionary<int, Exception>();
var relatedObjectsTasks = primaryObjectInfos.Select(async primaryObjectInfo =>
{
try
{
var secondaryObject = await objectManager.GetRelatedObjectsAsync(primaryObjectInfo);
allSecondaries.Add(Tuple.Create(primaryObjectInfo.Index, secondaryObject.ToList()));
}
catch (Exception ex)
{
exceptionsDict.TryAdd(primaryObjectInfo.Index, ex);
}
});
await Task.WhenAll(relatedObjectsTasks);
return ConvertToBulkResponse(allSecondaries, exceptionsDict);
}
When I run this code allSecondaries object sometimes returns valid list of results and sometimes the code ends up catching exceptions for the parallel threads I have for each primaryObjectInfo.
Async method objectManager.GetRelatedObjectsAsync() internally call 4-5 async functions and there are functions where parameters are passed by reference. (ref keyword)
Question:
Am I using the right data structure to consolidate the result from all parallel threads ?
If yes, what could be the reason I am getting different result every time?
You'd better split the execution from the results gathering:
public Task<BulkResponse<JObject>> GetRelatedObjectsAsync(
IEnumerable<PrimaryObjectInfo> primaryObjectInfos)
{
var relatedObjectsTasks = primaryObjectInfos
.Select(
async primaryObjectInfo =>
(primaryObjectInfo.Index,
await objectManager.GetRelatedObjectsAsync(primaryObjectInfo)))
.ToList();
try
{
await Task.WhenAll(relatedObjectsTasks);
}
catch
{
// observe each task's, exception
}
var allSecondaries = new List<(int index, List<JObject> related)>();
var exceptionsDict = new Dictionary<int, Exception>();
foreach (var relatedObjectsTask in relatedObjectsTasks)
{
try
{
allSecondaries.Add(relatedObjectsTask.Result);
}
catch (Exception ex)
{
exceptionsDict.Add(relatedObjectsTask.index, ex);
}
}
return ConvertToBulkResponse(allSecondaries, exceptionsDict);
}
You could look into each task's IsFaulted/Exception and IsCancelled properties instead of causing exceptions to be thrown:
foreach (var relatedObjectsTask in relatedObjectsTasks)
{
if (relatedObjectsTask.IsCancelled)
{
exceptionsDict.Add(
relatedObjectsTask.index,
new TaskCancelledException(relatedObjectsTask));
}
else if (relatedObjectsTask.IsFaulted)
{
exceptionsDict.TryAdd(relatedObjectsTask.index, ex);
}
else
{
allSecondaries.Add(relatedObjectsTask.Result);
}
}
Is there any way to write a LINQ style "short hand" code for walking to all levels of InnerException(s) of Exception thrown? I would prefer to write it in place instead of calling an extension function (as below) or inheriting the Exception class.
static class Extensions
{
public static string GetaAllMessages(this Exception exp)
{
string message = string.Empty;
Exception innerException = exp;
do
{
message = message + (string.IsNullOrEmpty(innerException.Message) ? string.Empty : innerException.Message);
innerException = innerException.InnerException;
}
while (innerException != null);
return message;
}
};
Unfortunately LINQ doesn't offer methods that could process hierarchical structures, only collections.
I actually have some extension methods that could help do this. I don't have the exact code in hand but they're something like this:
// all error checking left out for brevity
// a.k.a., linked list style enumerator
public static IEnumerable<TSource> FromHierarchy<TSource>(
this TSource source,
Func<TSource, TSource> nextItem,
Func<TSource, bool> canContinue)
{
for (var current = source; canContinue(current); current = nextItem(current))
{
yield return current;
}
}
public static IEnumerable<TSource> FromHierarchy<TSource>(
this TSource source,
Func<TSource, TSource> nextItem)
where TSource : class
{
return FromHierarchy(source, nextItem, s => s != null);
}
Then in this case you could do this to enumerate through the exceptions:
public static string GetaAllMessages(this Exception exception)
{
var messages = exception.FromHierarchy(ex => ex.InnerException)
.Select(ex => ex.Message);
return String.Join(Environment.NewLine, messages);
}
You mean something like this?
public static class Extensions
{
public static IEnumerable<Exception> GetInnerExceptions(this Exception ex)
{
if (ex == null)
{
throw new ArgumentNullException("ex");
}
var innerException = ex;
do
{
yield return innerException;
innerException = innerException.InnerException;
}
while (innerException != null);
}
}
This way you could LINQ over your entire exceptions hierarchy, like this:
exception.GetInnerExceptions().Where(e => e.Message == "Oops!");
How about this code:
private static string GetExceptionMessages(this Exception e, string msgs = "")
{
if (e == null) return string.Empty;
if (msgs == "") msgs = e.Message;
if (e.InnerException != null)
msgs += "\r\nInnerException: " + GetExceptionMessages(e.InnerException);
return msgs;
}
Usage:
Console.WriteLine(e.GetExceptionMessages())
Example of output:
There was no endpoint listening at
http://nnn.mmm.kkk.ppp:8000/routingservice/router that could accept
the message. This is often caused by an incorrect address or SOAP
action. See InnerException, if present, for more details.
InnerException: Unable to connect to the remote server
InnerException: No connection could be made because the target machine
actively refused it 127.0.0.1:8000
For those, who are waiting for a one-liner.
exc.ToString();
This will go through all your inner exceptions and return all messages, the downside is that it will also contain stack traces, etc.
You don't need extension methods or recursive calls:
try {
// Code that throws exception
}
catch (Exception e)
{
var messages = new List<string>();
do
{
messages.Add(e.Message);
e = e.InnerException;
}
while (e != null) ;
var message = string.Join(" - ", messages);
}
LINQ is generally used to work with collections of objects. However, arguably, in your case there is no collection of objects (but a graph). So even though some LINQ code might be possible, IMHO it would be rather convoluted or artificial.
On the other hand, your example looks like a prime example where extension methods are actually reasonable. Not to speak of issues like reuse, encapsulation, etc.
I would stay with an extension method, although I might have implemented it that way:
public static string GetAllMessages(this Exception ex)
{
if (ex == null)
throw new ArgumentNullException("ex");
StringBuilder sb = new StringBuilder();
while (ex != null)
{
if (!string.IsNullOrEmpty(ex.Message))
{
if (sb.Length > 0)
sb.Append(" ");
sb.Append(ex.Message);
}
ex = ex.InnerException;
}
return sb.ToString();
}
But that is largely an issue of taste.
I don't think so, exception is not an IEnumerable so you can't perform a linq query against one on its own.
An extension method to return the inner exceptions would work like this
public static class ExceptionExtensions
{
public static IEnumerable<Exception> InnerExceptions(this Exception exception)
{
Exception ex = exception;
while (ex != null)
{
yield return ex;
ex = ex.InnerException;
}
}
}
you could then append all the messages using a linq query like this:
var allMessageText = string.Concat(exception.InnerExceptions().Select(e => e.Message + ","));
To add to others, you may want to let the user decide on how to separate the messages:
public static string GetAllMessages(this Exception ex, string separator = "\r\nInnerException: ")
{
if (ex.InnerException == null)
return ex.Message;
return ex.Message + separator + GetAllMessages(ex.InnerException, separator);
}
public static string GetExceptionMessage(Exception ex)
{
if (ex.InnerException == null)
{
return string.Concat(ex.Message, System.Environment.NewLine, ex.StackTrace);
}
else
{
// Retira a última mensagem da pilha que já foi retornada na recursividade anterior
// (senão a última exceção - que não tem InnerException - vai cair no último else, retornando a mesma mensagem já retornada na passagem anterior)
if (ex.InnerException.InnerException == null)
return ex.InnerException.Message;
else
return string.Concat(string.Concat(ex.InnerException.Message, System.Environment.NewLine, ex.StackTrace), System.Environment.NewLine, GetExceptionMessage(ex.InnerException));
}
}
Most solutions presended here have the following implementation errors:
handle null exceptions
handle the inner exceptions of AggregateException
define a max depth for recurse inner exceptions (ie. with circular dependencies)
A better implementation is this here:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public static string AggregateMessages(this Exception ex) =>
ex.GetInnerExceptions()
.Aggregate(
new StringBuilder(),
(sb, e) => sb.AppendLine(e.Message),
sb => sb.ToString());
public static IEnumerable<Exception> GetInnerExceptions(this Exception ex, int maxDepth = 5)
{
if (ex == null || maxDepth <= 0)
{
yield break;
}
yield return ex;
if (ex is AggregateException ax)
{
foreach(var i in ax.InnerExceptions.SelectMany(ie => GetInnerExceptions(ie, maxDepth - 1)))
yield return i;
}
foreach (var i in GetInnerExceptions(ex.InnerException, maxDepth - 1))
yield return i;
}
Example usage:
try
{
// ...
}
catch(Exception e)
{
Log.Error(e, e.AggregateMessages());
}
I'm just going to leave the most concise version here:
public static class ExceptionExtensions
{
public static string GetMessageWithInner(this Exception ex) =>
string.Join($";{ Environment.NewLine }caused by: ",
GetInnerExceptions(ex).Select(e => $"'{ e.Message }'"));
public static IEnumerable<Exception> GetInnerExceptions(this Exception ex)
{
while (ex != null)
{
yield return ex;
ex = ex.InnerException;
}
}
}
public static class ExceptionExtensions
{
public static IEnumerable<Exception> GetAllExceptions(this Exception ex)
{
Exception currentEx = ex;
yield return currentEx;
while (currentEx.InnerException != null)
{
currentEx = currentEx.InnerException;
yield return currentEx;
}
}
public static IEnumerable<string> GetAllExceptionAsString(this Exception ex)
{
Exception currentEx = ex;
yield return currentEx.ToString();
while (currentEx.InnerException != null)
{
currentEx = currentEx.InnerException;
yield return currentEx.ToString();
}
}
public static IEnumerable<string> GetAllExceptionMessages(this Exception ex)
{
Exception currentEx = ex;
yield return currentEx.Message;
while (currentEx.InnerException != null)
{
currentEx = currentEx.InnerException;
yield return currentEx.Message;
}
}
}
With AggregateException
public static List<Exception> GetInnerExceptions(this Exception e)
{
List<Exception> eList = new List<Exception>();
if (e is AggregateException)
{
eList.AddRange((e as AggregateException).InnerExceptions);
}
else
{
eList.Add(e);
}
List<Exception> ieList = eList
.Where(i => i.InnerException != null)
.SelectMany(i => i.InnerException.GetInnerExceptions())
.ToList();
eList.AddRange(ieList);
return eList;
}
Just use the following code.
catch(Exception ex)
{
Exception currentEx = ex;
while (currentEx.InnerException != null)
{
currentEx = currentEx.InnerException;
}
return currentEx;
}
After 9+ years the original question still begs for an answer.
Not exactly short, but yes, it can be done LINQ-style in a single statement:
var ex1 = new NullReferenceException("EX1");
var ex2 = new InvalidCastException("EX2", ex1);
var ex3 = new InvalidOperationException("EX3", ex2);
const int maxDepth = 10;
var message = Enumerable.Range(1, maxDepth).Aggregate(
new { s = $"{ex3.GetType().Name} - {ex3.Message}", ex = ex3.InnerException },
(v, i) => v.ex != null
? new { s = v.s + $"\nInner exception {i}: {v.ex.GetType().Name} - {v.ex.Message}",
ex = v.ex.InnerException }
: new { s = v.s, ex = (Exception)null },
v => v.s);
/* message is:
InvalidOperationException - EX3
Inner exception 1: InvalidCastException - EX2
Inner exception 2: NullReferenceException - EX1
*/
The key is to use Enumerable.Range().Aggregate() for iteration and a value v of anonymous type (introduced in C# 3.0) holding both
the result v.s being built up, as well as
the current exception v.ex as we're walking down the list.
(StringBuilder left out to reduce clutter.)
I used combination of Select and Join:
Unit test:
[Test]
public void FirendlyErrorMessage_Tests()
{
// Arrange
Exception ex = new AggregateException(new Exception("MY_ERROR_MESSAGE_FROM_DCE_1"), new Exception("MY_ERROR_MESSAGE_FROM_DCE_2"), new Exception("MY_ERROR_MESSAGE_FROM_DCE_3"));
// Assert
var e = Assert.Throws<Exception>(() => ErrorHandler.RaiseFirendlyErrorMessage(ex));
Assert.AreEqual(e.Message, "One or more errors occurred. Possible reasons: MY_ERROR_MESSAGE_1, MY_ERROR_MESSAGE_2, MY_ERROR_MESSAGE_3");
}
ErrorHandler class:
public void RaiseFirendlyErrorMessage(Exception ex)
{
if (ex is AggregateException)
{
var aggrEx = ex as AggregateException;
string aggregateExcMessage = ex.Message + $" Possible reasons: { string.Join(", ", aggrEx.InnerExceptions.Select(s => s.Message)) }";
throw new Exception(aggregateExcMessage);
}
}
Final message will be:
"One or more errors occurred. Possible reasons: MY_ERROR_MESSAGE_1, MY_ERROR_MESSAGE_2, MY_ERROR_MESSAGE_3"
I get the following error on the seminariolista = line:
Cannot implicitly convert type from IOrderedQueryable to List
public List<Seminario> Listarseminariomodal()
{
var seminariolista = new List<Seminario>();
try
{
using (var ctx = new ProyectoContext_())
{
seminariolista = ctx.Seminario.Where(x => x.modal == 1)
.OrderBy(x => x.orden);
}
}
catch (Exception)
{
throw;
}
return seminariolista;
}
Visual Studio Screenshot
Probably defining it as
IEnumerable<Seminario> seminariolista = null;
and returning it as
return seminariolista.ToList();
will work.
But in general it's not a good idea, in my opinion, to return a List object, unless you explicitly need it. I would return an IEnumeralble, to keep the method signature as general as possible.
So, the best solution for your code, in my opinion and WITHOUT KNOWING the requirement of your application and the rest of your code:
public IEnumerable<Seminario> Listarseminariomodal()
{
IEnumerable<Seminario> seminariolista = null;
try
{
using (var ctx = new ProyectoContext_())
{
seminariolista = ctx.Seminario.Where(x => x.modal == 1)
.OrderBy(x => x.orden);
}
}
catch (Exception)
{
throw;
}
return seminariolista.ToArray();
}
Note the ToArray() call at the end, to hide the LINQ stuff outside the method body.
I want get data from Azure. This is my code:
private async void FindPromotion()
{
MobileServiceCollection<Promotions, Promotions> result;
MobileServiceInvalidOperationException exception = null;
string _place = textInputPlace.Text;
if (_place!= null)
{
try
{
//lista obiektów Category
result = await todoTable2.Where(todoItem => todoItem.Place==_place)
.Select(todoItem => todoItem.Products, todoItem => todoItem.Description)
.ToCollectionAsync();
}
catch (MobileServiceInvalidOperationException ex)
{
exception = ex;
}
if (exception != null)
{
await new MessageDialog(exception.Message, "Can't find items").ShowAsync();
}
else
{
ListItems.ItemsSource = result.Distinct();
}
}
}
I have error:
No overload for method 'Select' takes 2 arguments.
Anybody know? Is another way to get this data?
This is how you can select multiple columns:
result = await todoTable2.Select(todoItem => new { todoItem.Products , todoItem.Description}).ToCollectionAsync();
I have some code that looks like this:
public Tuple<bool, SomeObjectModel> CheckIfJsonIsValid(string IncomingJson)
{
SomeObjectModel TheObjectModel = new SomeObjectModel();
JavascriptSerializer TheSerializer = new JavascriptSerializer();
.....
try
{
TheObjectModel = TheSerializer.Deserialize<SomeObjectModel>(IncomingJson);
}
catch
{
return new Tuple<bool, SomeObjectModel>(false, null); //question here
}
.....
return new Tuple<bool, SomeObjectModel>(true, TheObjectModel);
}
The calling method first check the returning tuple's Item1, and if it's false, ends its process.
Is it better practice a) to return a null value in the Tuple or b) to return a new and fresh instance of SomeObjectModel? Are there any performance implications?
Thanks for your suggestions.
Let me suggest three alternative solutions:
ParseJsonIfValid: If deserializing works, TheObjectModel is always non-null. Thus, there is no need for the boolean:
public SomeObjectModel ParseJsonIfValid(string IncomingJson)
{
JavascriptSerializer TheSerializer = new JavascriptSerializer();
.....
try
{
return TheSerializer.Deserialize<SomeObjectModel>(IncomingJson);
}
catch
{
return null;
}
}
In the calling function simply check whether the return value is null or not.
ParseJson: If the JSON is usually valid, and invalid JSON is a sign of something gone terribly wrong, just throw an exception:
public SomeObjectModel ParseJson(string IncomingJson)
{
JavascriptSerializer TheSerializer = new JavascriptSerializer();
.....
try
{
return TheSerializer.Deserialize<SomeObjectModel>(IncomingJson);
}
catch (Exception e)
{
throw new TheServerSentRubbishException(e);
}
}
Be sure to include the inner ("real") exception, so that the calling function can log the real cause of the error for debugging purposes.
TryParseJson: If null can be a valid deserialization, you can use the following pattern, which has the advantage of being consistent with the TryParse methods of the .NET framework:
public bool TryParseJson(string IncomingJson, out SomeObjectModel theObjectModel)
{
JavascriptSerializer TheSerializer = new JavascriptSerializer();
.....
try
{
theObjectModel = TheSerializer.Deserialize<SomeObjectModel>(IncomingJson);
return true;
}
catch (Exception e)
{
return false;
}
}