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.
Related
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.
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>.
I am working on a project to connect to PostgreSQL database using NpGsql EntityFramework 6. I am getting the exception in question heading, when I try to execute the query in GetAdminUsersCount:
public class GenieRepository : IDisposable
{
GenieDbContext db = new GenieDbContext();
public IEnumerable<User> GetUsers()
{
return db.Users;
}
}
public int GetAdminUsersCount()
{
return repo.GetUsers().Where(u => u.Role.RoleName == "Administrator").Count();
}
What is the reason for this error and how to resolve it?
Use a ToList<T> right after the LINQ query like this:
using (ElisContext db = new ElisContext()) {
var q = from a in db.aktie select a;
List<aktie> akties = q.ToList<aktie>();
foreach (aktie a in akties) {
Console.WriteLine("aktie: id {0}, name {1}, market name {2}"
, a.id, a.name, a.marked.name);
}
}
Note the q.ToList<T> which does the trick. .NET delays the execution of the linq statement to the latest moment, which may be part of the problem. I have tried to use q in the foreach without success.
The issue is caused by the return type of the GetUsers() method. Since it is IEnumerable<User>, LINQ-to-SQL will load the result into memory (row by row) and subsequent Where, OrderBy, Select, Count, etc. calls will be executed in memory. When the Where condition is evaluated, the original result set is still being iterated over, but the relation User.Role needs to be resolved on the DB (that's where the "An operation is already in progess" error message comes from).
If the return type is changed to IQueryable<User>, the query won't be executed until the Count method is called, and furthermore, the whole query will be translated into SQL returning only the count without ever loading any User records into memory.
See also this related question/answer: Returning IEnumerable<T> vs. IQueryable<T>
The answer suggesting to call ToList() on the query, will load the entire result set into memory, which makes your error go away, but depending on the size of the result set, could also be very inefficient.
I have this weird issue with Entity Framework with the code snippet below
var userWorkItems = (from uw in context.UserWorkItems
join u in context.DNN_Users on uw.UserID equals u.UserID
where u.Username.StartsWith(fromUserName)
select uw).ToList();
if (userWorkItems != null)
{
for (int i = 0; i < userWorkItems.Count; i++)
{
userWorkItems[i].UserID = toUserID.Value;
}
context.SubmitChanges();
}
The whole table gets updated with the Userid of the fromUserName when an exception occurs.
What kind of exception leads to this kind of weird behavior, though a try catch has been added now to the context.SubmitChanges();
Or are we making the wrong conclusion?
Where does the exception occur and what is the exception? I believe your issue might be fromUserName. If it was an empty string, it would return every single UserWorkItem. If an error is thrown and you don't want it to do a partial save on the context, wrap it in a TransactionScope like so.
using(var scope = new TransactionScope()){
//Do whatever
scope.Complete();
}
Sharing the code below please any one tell what is the error
try
{
OrganoCollection = new ObservableCollection<HRM_Organogram>();
foreach (var jobTypeDef in LobjWsHrmOeLinking.GetUnOccupiedRecordSearch())
{
OrganoCollection.Add(jobTypeDef);
}
}
catch (Exception ex)
{
ApplicationClass.Message(ex.Message, "Error", MessageType.Error);
}
And the Definition of function is giving below this function is used throug a wcf service
public List<HRM_Organogram> GetUnOccupiedRecordSearch()
{
List<HRM_Organogram> p_objMaster = new List<HRM_Organogram>();
try
{
using (var context = new CMS_ERPEntities())
{
context.ContextOptions.LazyLoadingEnabled = false;
var l_objMaster = (from OG in context.HRM_Organogram
join OE in context.HRM_OELinking
on OG.OrganoID equals OE.OrganoID
where OE.FinalizeStatus == true
select OG.OrganoID).ToList();
p_objMaster = (from OG in context.HRM_Organogram
where !l_objMaster.Contains(OG.OrganoID)
&& OG.Isactive==true
select OG).ToList();
}
}
catch (Exception ex)
{
throw ex;
}
return p_objMaster;
}
And The Error is:
Argument Type CMS_ERPClient.Service.HRM_OeLinking.HRM_Organogram is
Not Assianable to CMS_ERPClient.Service.HRM_OrganGram.HRM_OrganGram
There is more than one type called HRM_Organogram, one in the namespace CMSERPClient_Service.HRM_OElinking and one in the namespace CMS_ERPClientService.HRMORganogram. You are trying to add the latter to a collection of the former. Check your using statements.
And if I may say, your namespace and type names are awful! Refactor them to have more descriptive and distinctive names and you'll have a much more enjoyable coding experience!
My guess is one is a DTO type and one is a Model type, and you'll have a mapper somewhere to do a conversion. I also guess this sentence won't mean a whole lot to you - try to see how these types are used elsewhere and look for code that has using statements for both and converts one to the other.