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.
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.
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>.
public int getPartijId(string naam)
{
Partij partij = null;
try
{
partij = repository.Partij.Single<Partij>(p => p.naam.Equals(naam));
}
catch (InvalidOperationException)
{
}
return partij.partijID;
}
I want to get a certain value (CD&V) out of our database, by comparing the name in the database with a linq statement but I'm getting a null value back...
With the rest of the values, this method works, but I suspect the problem is '&' in the name/string
Maybe try if your repository of Partij are all partijen
partij = repository.Partij.First(p => p.naam.Equals(naam));
As far as I can tell, the only way your code can return null is if the partijID on the matched object is null.
Other options are throwing a null reference exception
Partij partij = null;
try
{
// this may throw an exception because there may be more or less than one item matching your predicate
partij = repository.Partij.Single<Partij>(p => p.naam.Equals(naam));
}
catch (InvalidOperationException)
{
// this is hiding that exception
}
// this will throw another null reference exception because the first call didn't actually set the partij variable
return partij.partijID;
P.S. It's almost never a good idea to catch an exception then completely ignore it.
How is your table designed? Does the naam field have a unique constraint on it? Are you 100% sure you have exactly one row with a value of "CD&V" in the naam field? My guess would be you're getting multiple rows back and then swallow the exception, so partij stays null.
What's the exception message exactly?
Is partijID actually null in the database?
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 have this code:
public article GetArticleByWebSite(string webSite)
{
using (var context = new ceopolandEntities())
{
return context.article.Where(a => a.WebSite == webSite).First();
}
}
What's the best way to check if article isn't empty before calling First()?
A try catch block or introduce a variable and check how many articles are there?
Try .FirstOrDefault();. It will return null if nothing is found.