try
{
return strngarray.Select(strngarrayelem =>
{
string[] data = strngarrayelem .Split(',');
return new xyzClass(data[1], data[2], data[0], (Color)System.Windows.Media.ColorConverter.ConvertFromString(data[3]), data.Length > 4 ? data[4] : "N/A");
});
}
catch (Exception ex)
{
MessageBox.Show("abc");
return Enumerable.Empty<xyzClass>();
}
I am getting format exception in
(Color)System.Windows.Media.ColorConverter.ConvertFromString(data[3])
I try catching it by try-catch but exception is still thrown by app level try catch and not caught by my local try catch.
Why my try catch not getting error ?
You are just returning a LINQ query, it's not yet executed(like for example with ToList).
So if you want to catch the exception here you should consider materializing it to a collection in this method. You could still return IEnumerable<xyzClass> since List<xyzClass> implements that interface.
try
{
return strngarray.Select(strngarrayelem =>
{
string[] data = strngarrayelem .Split(',');
return new xyzClass(data[1], data[2], data[0], (Color)System.Windows.Media.ColorConverter.ConvertFromString(data[3]), data.Length > 4 ? data[4] : "N/A");
}).ToList(); // <------- HERE !!!
}
catch (Exception ex)
{
MessageBox.Show("abc");
return Enumerable.Empty<xyzClass>();
}
If you don't know which method is just returning a query, look at the documentation in MSDN for the keyword deferred. For example Enumerable.Select:
This method is implemented by using deferred execution. The
immediate return value is an object that stores all the information
that is required to perform the action. The query represented by this
method is not executed until the object is enumerated either by
calling its GetEnumerator method directly or by using
foreach
Methods like for example Enumerable.ToList or ToArray call GetEnumerator, so they will execute the query. MSDN:
The ToList<TSource>(IEnumerable<TSource>) method forces immediate
query evaluation and returns a List<T> that contains the query
results. You can append this method to your query in order to obtain a
cached copy of the query results.
ToArray<TSource> has similar behavior but returns an array instead of
a List<T>.
Related
I'm trying to catch errors when calling a procedure in Entity Framework Core 3.0, but it never hits the catch block. I tried forcing a couple of common errors like the wrong procedure name, or wrong number of parameters.
I can actually step through the code, which doesn't error out, and I can see these messages in the results view.
Invalid object name...
An insufficient number of arguments were supplied for the procedure or function...
What am I missing here? How can I catch errors like this?
try
{
IEnumerable<Users> result = (from x in _db.Users.FromSqlRaw("Execute ustp_MyProcedure)").AsEnumerable()
select x);
return result;
}
catch (Exception ex)
{
//Never gets here
}
UPDATE
I'm still confused why EntityFramework Core 3.0 would behave differently than EF6 that I'm using in an older MVC application. I'm still using IEnumerable here, but errors in this setup DO end up in the catch block.
private DatabseEntities db = new DatabseEntities();
public IEnumerable<ustp_MyProcedure_Result> MyMethod(string searchString)
{
try
{
var result= (from p in db.ustp_MyProcedure(searchString)
select p);
return sourceQuery;
}
catch (Exception ex)
{
//Even as an IEnumerable, errors DO end up in this catch block
}
}
You are assigning the result of a query to an IEnumerable variable. IEnumerable represents an unmaterialized collection. It doesn't have any items inside until it is enumerated. The database query, which you've assigned to the IEnumerable will be executed only, when the IEnumerable is enumerated.
This happens for instance, when you use it in a foreach loop, call a ToList(), ToArray() or any other LINQ method on it.
You are only getting the exception in results view. Because checking the results view materializes the collection and executes the DB query.
If you change your code to:
try
{
IEnumerable<Users> result = (from x in _db.Users.FromSqlRaw("Execute ustp_MyProcedure)").AsEnumerable()
select x);
return result.ToList();
}
catch (Exception ex)
{
//Never gets here
}
The exception will be raised in the try block.
I have the following statement that I am trying to use a try-catch block with
var val= db.shops.where(x=>×.id==ID).Select (a=>a.address).First();
I tried following but has many issues won't even compile.
var val=db.shops.Where(x=>
{
try
{
(x.Id==ID).Select(a=>a.address).First();
}
catch(ex)
{
return ex;
}
}
Please let me know how can I handle the exception in this statement Thanks.
Note: writing this question from mobile phone can't format code. Apologize for it.
Everything inside brackets ({ }) need to have 'regular' block syntax, so return is required here:
...
.Where
(x=>
{
try
{
return (x.Id == ID);
}
catch(ex)
{
throw;
}
}
)
.Select(a=>a.address)
.First(); // Or FirstOrDefault if you expect this statement to yield no result.
As you see, the Where is more like a regular statement now. The Select is moved to outside the Where. If you need exception handling in there, you have to do the same as in the Where block now. Last, return ex is probably meant to be throw ex, which should be throw in this case to preserve call stack.
...that I am trying to use try catch block with
I am guessing you probably meant to write FirstOrDefault based on where you want the try/catch. In the sample code you have provided I see no reason to try to make a catch block into one of the lambda statements. The best thing to do would be to simply use FirstOrDefault as that is the reason why you might get an exception in the code shown.
var address = db.shops.FirstOrDefault(x => ×.id == ID)?.Address;
if(address == null)
// nothing was found or address is null, do something else
Or similar code closer to what you had without my "optimization"
var shop = db.shops.FirstOrDefault(x => ×.id == ID);
if(shop == null) {
// nothing was found, do something else
}
var address = shop.address;
The other reason not to use try/catch is that it can't be translated into SQL and the variable name db which is the container for the shops collection which leads me to believe you are using EF or some other ORM. So even if you were to fix the syntax and your code with added try/catch block compiles you will get a run time error later when you execute the lambda.
You should place the try around your original statement:
try
{
var val= db.shops.where(x=>×.id==ID).Select (a=>a.address).First();
}
catch (Exception ex)
{
return ex; //I assume the return type here is wrong. Maybe return null?
}
However, there's nothing about that line that should require a try/catch. Try this:
var val= db.shops.where(x=>×.id==ID).Select(a=>a.address).FirstOrDefault();
The FirstOrDefault will return null if there are no results.
According to MS documentation, the enumerator should throw InvalidOperationEx, if the underlying enumerated source was modified. This works when I just get the enumerator directly from IEnumerable.
THE PROBLEM: But if I acquire enumerator from "query data structure" , then modify the source and then call MoveNext(), nothing is thrown (see the code).
Consider following code:
public static void Main(string[] args)
{
var src = new List<int>() { 1, 2, 3, 4 };
var q = src.Where(i => i % 2 == 1);
IEnumerable<int> nl = src;
var enmLinq = q.GetEnumerator();
var enmNonLinq = nl.GetEnumerator();
src.Add(5); //both enumerators should be invalid, as underlying data source changed
try
{
//throws as expected
enmNonLinq.MoveNext();
}
catch (InvalidOperationException)
{
Console.WriteLine("non LINQ enumerator threw...");
}
try
{
//DOES NOT throw as expected
enmLinq.MoveNext();
}
catch (InvalidOperationException)
{
Console.WriteLine("enumerator from LINQ threw...");
}
//It seems that if we want enmLinq to throw exception as expected:
//we must at least once call MoveNext on it (before modification)
enmLinq.MoveNext();
src.Add(6);
enmLinq.MoveNext(); // now it throws as it should
}
It seems you must first call MoveNext() method to made it notice the change of underlying source.
Why I think this is happening:
I think this is because the "query structure" is giving you too lazy enumerator, which instead of being initialized on GetEnumerator() is initialized during first call to MoveNext().
By initialization I mean connecting all of the enumerators (from WhereEnumerable, SelectEnumerable etc structures returned by LINQ methods) on the way down to the real underlying data structure.
QUESTION:
Am I right about this or am I missing something?
Do you consider it as weird/wrong behaviour?
You are correct.
The LINQ query will not call GetEnumerator on the underlying List<T> until you call MoveNext on the IEnumerable<T> returned by Where.
You can see in the reference source that MoveNext is implemented like so:
public override bool MoveNext()
{
switch (state)
{
case 1:
enumerator = source.GetEnumerator();
state = 2;
goto case 2;
case 2:
while (enumerator.MoveNext())
{
TSource item = enumerator.Current;
if (predicate(item))
{
current = item;
return true;
}
}
Dispose();
break;
}
return false;
}
In the 'initial' state (state 1), it will first call GetEnumerator on the source before moving to state 2.
The documentation only states execution is deferred until the object is enumerated either by calling its GetEnumerator method directly or by using foreach in Visual C# or For Each in Visual Basic.
Since it lacks further detail, the queries performed by LINQ may call GetEnumerator on their source either on the first call to their own GetEnumerator or as late as possible, such as the first call to MoveNext.
I wouldn't assume any particular behavior.
In practice, the actual implementation (see Enumerable.WhereEnumerableIterator<TSource> in the reference source) defers execution to the first call to MoveNext.
enmLinq is not actualized until first MoveNext call. So, any modification done to the src prior to calling MoveNext will not affect validity of enmLinq. Once you call MoveNext on enmLinq - enumerator is actualized, hence any changes on src will lead to exception for the subsequent MoveNext call.
You can test this yourself.
public static void Main(string[] args)
{
var src = new List<int>() { 1, 2, 3, 4 };
var q = src.Where(i =>
{
Output();
return i % 2 == 1;
}
);
IEnumerable<int> nl = src;
var enmLinq = q.GetEnumerator();
var enmNonLinq = nl.GetEnumerator();
src.Add(5); //both enumerators should be invalid, as underlying data source changed
try
{
//throws as expected
enmNonLinq.MoveNext();
}
catch (InvalidOperationException)
{
Console.WriteLine("non LINQ enumerator threw...");
}
try
{
//DOES NOT throw as expected
// Output() is called now.
enmLinq.MoveNext();
}
catch (InvalidOperationException)
{
Console.WriteLine("enumerator from LINQ threw...");
}
//It seems that if we want enmLinq to throw exception as expected:
//we must at least once call MoveNext on it (before modification)
enmLinq.MoveNext();
src.Add(6);
enmLinq.MoveNext(); // now it throws as it should
}
public static void Output()
{
Console.WriteLine("Test");
}
When you run the program, you will see that "Test" is not output to the console until after you call your first MoveNext, which occurs after the source was initially modified.
Built a custom IDataReader which goes looking in XML for values that match particular element names and, if found, returns the values. The GetValue function - which has to return an Object, as specified by the interface, looks like this:
public object GetValue(int i)
{
string SearchString = _columns[i];
var searchedAttributeValue = from nm in _el.Attributes(SearchString) select nm;
if (searchedAttributeValue.Count() > 0)
{
return ParseTypes(searchedAttributeValue.First().Value);
}
var searchedElementValue = from nm in _el.Elements(SearchString) select nm;
if (searchedElementValue.Count() > 0)
{
return ParseTypes(searchedElementValue.First().Value);
}
}
This won't build, obviously, because it's possible to reach the end of the function without a valid return.
In this instance, if that happens, it means there's a config error - the user is looking for an element or attribute in the XML that's not there.
I discovered (this was new to me) that you can get round the problem by doing this:
public object GetValue(int i)
{
if (_el == null)
{
_el = XNode.ReadFrom(_reader) as XElement;
}
string SearchString = _columns[i];
var searchedAttributeValue = from nm in _el.Attributes(SearchString) select nm;
if (searchedAttributeValue.Count() > 0)
{
return ParseTypes(searchedAttributeValue.First().Value);
}
var searchedElementValue = from nm in _el.Elements(SearchString) select nm;
if (searchedElementValue.Count() > 0)
{
return ParseTypes(searchedElementValue.First().Value);
}
throw new Exception("oh crap!");
}
So the function doesn't return, it just throws an error.
However, something feels fundamentally wrong with this approach. Is it okay, why is it okay/not okay and is there a better way to handle the situation?
Well unless you really need the catch block, you don't need to introduce try/catch/finally. You can just add a throw statement at the end of your initial method.
Along the way, I'd start using FirstOrDefault(), follow normal C# naming conventions for local variables, stop using query expressions when they're not terribly useful, and throw a more specific exception:
public object GetValue(int i)
{
string searchString = _columns[i];
var searchedAttribute = _el.Attributes(searchString).FirstOrDefault();
if (searchedAttribute != null)
{
return ParseTypes(searchedAttribute.Value);
}
var searchedElement = _el.Elements(searchString).FirstOrDefault();
if (searchedElement != null)
{
return ParseTypes(searchedElement.Value);
}
// Nothing found - oops.
throw new SomeSpecificException("Some message here");
}
If you need the catch block for logging, I'd probably try to catch a specific exception, which probably means moving that into ParseTypes anyway (as you shouldn't get any exceptions from the rest of the calls...) Either way, keep the throw statement at the end.
EDIT: In terms of design, whether you should throw an exception when the value isn't found or not really depends on the expectations. We have no way of knowing whether that indicates something wrong with the system, or just a perfectly normal absence of data. That should determine your choice here. In particular, if every caller is going to try to catch the exception, then that's a design smell and you should either return null or use something like the Dictionary<,>.TryGetValue approach.
I like to make my methods similar to the .NET framework Parse() and TryParse() methods. In your case I would either do:
public object GetValue(int i)
{
// ...
// fail
throw new Exception("Cannot get value");
}
or do:
public bool TryGetValue(int i, out object result)
{
// ...
// fail
result = null;
return false;
}
The try catch is irrelvant. you could simply refactor your code to:
public object GetValue(int i)
{
if (_el == null)
{
_el = XNode.ReadFrom(_reader) as XElement;
}
string SearchString = _columns[i];
var searchedAttributeValue = from nm in _el.Attributes(SearchString) select nm;
if (searchedAttributeValue.Count() > 0)
{
return ParseTypes(searchedAttributeValue.First().Value);
}
var searchedElementValue = from nm in _el.Elements(SearchString) select nm;
if (searchedElementValue.Count() > 0)
{
return ParseTypes(searchedElementValue.First().Value);
}
throw new Exception("oh crap!");
}
this has the same net result.
That said throwing exceptions are expensive (computationaly). If you want this to bomb out (stop processing completly, this is a major problem and it should simply die) then thrown an exception.
If it's simply a way to identify when the if statements are not being met maybe change it to a TryParse type function:
public bool GetValue(int i, out object returnVal)
{
if (_el == null)
{
_el = XNode.ReadFrom(_reader) as XElement;
}
string SearchString = _columns[i];
var searchedAttributeValue = from nm in _el.Attributes(SearchString) select nm;
if (searchedAttributeValue.Count() > 0)
{
returnVal = ParseTypes(searchedAttributeValue.First().Value);
return true;
}
var searchedElementValue = from nm in _el.Elements(SearchString) select nm;
if (searchedElementValue.Count() > 0)
{
returnVal = ParseTypes(searchedElementValue.First().Value);
return true;
}
return false;
}
then
if (GetValue(i, out value))
//success
else
//it's failed.
If it is genuinely an exceptional circumstance that the search won't return anything because the configuration is wrong, then by all means, throw an exception. The problem with this is continuation. Can client code continue if an item isn't found? If it can, client code will need to closely examine any exception thrown from your code to determine if it was thrown because an item didn't exist, or because something else went wrong that can't be continued from.
The other option is to return something that indicates that the value wasn't found, and allow calling code to deal with it. You could return null to indicate to calling code that no item was found, and that might be fine in this instance. A better solution might be to create a simple Optional<T> class, that contains an indication of whether the object existed (perhaps HasValue), and the object itself if it did. Calling code can easily and more concretely check whether an object was returned and deal with a situation where it isn't, and exceptions don't require additional scrutiny.
EDIT: A better alternative altogether might be the Parse and TryParse paradigm suggested by others, but I think this answer might have some use, so I'll leave it here :)
There are quite a few bad practices in this approach: catch (Exception) should always be avoided. Only catch the exceptions you expect there. Also, throw Exception() is bad style. Always throw something more specific. But for what you're looking for: You don't need a finally after all, just place a throw new ArgumentException() or something as the last line of the function. That is good practice, if it is really a programming error if the code ever runs there.
I noticed some weird behavior in LINQ-code, and reduced the problem to the following minimal example with two methods:
IA Find(string n)
{
IA result;
if (!_dictionary.TryGetValue(n, out result))
{
throw Exception();
}
return result;
}
IEnumerable<IA> Find(IEnumerable<string> names)
{
return names.Select(Find).ToArray();
}
This works as expected.
Now, I remove the .ToArray() so the method looks as follows:
IEnumerable<IA> Find(IEnumerable<string> names)
{
return names.Select(Find);
}
This change will cause the exception not to be thrown, even if some of the names are not found in _dictionary, but are present in the names parameter.
What causes this (to me) unexpected behavior of LINQ?
Its because of deferred execution. The Linq is not evaluated until you execute it.
The call to ToArray() causes a full enumeration of the IEnumerable and thus, the exception to occur.
The second method does not enumerate the IEnumerable and execution is deferred until the caller needs it.
If you were to enumerate the result of Find e.g.
var result = Find(new[] { "name" }).ToList();
or
foreach (var found in Find(new[] { "name" }))
{
...
}
then the exception would occur.