Entity Framework does not catch SQL Exception - sql-server

I am using stored procedures and running the stored procedures using "FromSql" feature provided by Microsoft Entity framework Core.
When there is a SQL exception Entity Framework does not catch the exception at all.
For example below, the stored procedure "GetAppSections" is missing in SQL.When I run the app In the debug mode I can locate the "missing stored proc" error deep inside the local window.
However logic never goes to the "Catch" block.Entity Framework simply runs the 'FromSql' command and returns an empty object. The "catch" block is never hit.
Any idea why Entity Framework is not catching the "missing stored proc" exception from SQL?
public virtual IEnumerable<appSection> GetSections()
{
try
{
return _context.appSections.FromSql("dbo.GetAppSections #p0",
parameters: new[] { _standarParams.userID.ToString()}).AsEnumerable();
}
catch (Exception ex)
{
// error handling code
}
}

You are returning an IEnumerable which is deferred. You need the try catch block around the code that actually accesses that IEnumerable (ToList, ForEach, etc).
See here and here

Related

How to profile Entity Framework activity against SQL Server?

It's easy to use SQL Server Profiler to trace stored procedures activity. But how to trace SQL queries issued by LINQ via Entity Framework? I need to identify such queries (LINQ code) that consume a lot of time, are called most frequently and therefore are the first candidates for optimization.
Add this key to your connection string:
Application Name=EntityFramework
And filter by this in Profiler
Adding #ErikEJ's answer : if you are using .net Core, so you are using EFCore. There are no Database.Log property. You should use OnConfiguring override of your DbContext class and then
optionsBuilder.LogTo(Console.WriteLine);
Sample :
public class AppDbContext : DbContext
{
public DbSet<User> Users { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.LogTo(Console.WriteLine);
}
}
I've found useful DbContext.Database.Log property.
MSDN article Logging and Intercepting Database Operations
The DbContext.Database.Log property can be set to a delegate for any method that takes a string. Most commonly it is used with any TextWriter by setting it to the “Write” method of that TextWriter. All SQL generated by the current context will be logged to that writer. For example, the following code will log SQL to the console:
using (var context = new BlogContext())
{
context.Database.Log = Console.Write;
// Your code here...
}
What gets logged?
When the Log property is set all of the following will be logged:
The approximate amount of time it took to execute the command. Note that this is the time from sending the command to getting the result object back. It does not include time to read the results.
SQL for all different kinds of commands. For example:
Queries, including normal LINQ queries, eSQL queries, and raw queries from methods such as SqlQuery
Inserts, updates, and deletes generated as part of SaveChanges
Relationship loading queries such as those generated by lazy loading
Parameters
Whether or not the command is being executed asynchronously
A timestamp indicating when the command started executing
Whether or not the command completed successfully, failed by throwing an exception, or, for async, was canceled
Some indication of the result value

Strange behavior with try-catch on Dynamics Ax 2012

I'm trying without success to figure out what I'm doing wrong trying to handle one exception in my code, hopefully someone can help me.
I'm reading an external database from within Ax to integrate some customers. So I loop through a series of records using a ResultSet object. at a given point I have some code that looks like this:
while (resultSet.next())
{
//some logic (...)
ttsbegin;
//This is a custom table that stores to where I want to integrate the given customer
while select integrationCompany
where integrationCompany.CRMCompany == customerInfo.parmCRMDataAreaId()
{
changeCompany(integrationCompany.ERPCompany)
{
try
{
customerInfo.createCustomer();
//.. some more logic
}
catch
{
// My catch Block, that should update the source database to set
// the processing status to "error"
ttsAbort;
}
}
}
ttsCommit;
}
And inside the customerInfo.createCustomer() method I'm explicitly throwing some exceptions (throw Exception::Error) if some requirements aren't met.
The problem is that the catch block isn't reached - the program stops without getting back to the main routine.
Does it has something to do with the transaction opening/aborting/commiting or is something else?
AX (X++) is strange here (if you are used .NET/Java like try/catch scenario).
If you have try inside the transaction, then fist catch cathes the excation (which is Enum and not sort of exception object).
From the MSDN: Exceptions Inside Transactions:
When an exception is thrown inside a ttsBegin - ttsCommit transaction block, no catch statement inside that transaction block can process the exception. Instead, the innermost catch statements that are outside the transaction block are the first catch statements to be tested.

Display a message if user is unauthorised to run a stored procedure

I am new to stored procedures and am just curious how things are done. What I would like to know is how to display a message if a user tries to execute a procedure that he has no rights on ?
From what I can fathom, SQL Server itself takes care of the message. I tried this way (inside a stored procedure) :
BEGIN
try
DELETE from MYTABLE
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
and it makes no difference weather I write this or not. The error is the same. Didnt figure out how to write your own message though ...
If a user tries to execute a stored procedure or user-defined function (UDF) that they have not been granted permissions to, either explicitly or implicitly through one or more role memberships, then SQL Server will handle the exception and error message. You cannot set a message within that code as by definition the user is not allowed to execute it to get any error message or error handling that would be inside of it.
If you want a custom message, you need to catch the SQL Exception from the app side (there should be an error code that you can test for indicating "Permission Denied") and then just return your custom message.
There is fix message or say default message display when you try to access unauthorized object.
There is so many security feature comes, like user, role, schema etc. If anything mismatch, you get the error "Could not find stored procedure 'guest.get_procedureName'."
suppose I was created a procedure with default schema(dbo) the name procedure1.
exec dbo.procedure1 para1value,'para2value', null,para4value etc.
exec guest.procedure1 para1value,'para2value', null,para4value etc.
Now if everything fine, first one give me data to sql side and C# side.
But the second will give me the above error.
Nothing to handle in the sqlserver side for this type of security, As above your code, try catch is same work as C#, but ideally, it only need when you explicitly want the message from sql return to show directly to ui i.e. custom logic error message, while you run the sp or when mismatch the data etc.
For the c# point of view, you can get this message in catch, so you can do like.
public method
{
try
{
.....
}
catch(Exception ex)
{
if (ex.Message.Contains("Could not find"))
//give any your custom message or throw ex
}
}
try
DoTheThing();
except
on E:Exception
ShowMessage("Something Went Wrong! : " + E.Message);
end;
This shows a custom message (of sorts) and it also gives you a means to examine the contents of the error via 'E'.
You can also handle more specific exceptions
except
on E:ESomeSpecificException
// ----
end;
--
As others have pointed out - there is no point in trying to catch the error inside the stored proc - the user doesnt have access to it ... by definition

WCF service in WPF self host application crash when I throw a fault exception (async methods)

I have a service hosted in a WPF application with an async method with the Begin/end methods, and when I catch an exception in the service, I want to throw a faultException to warn to the client.
However, when I try to throw the faultException, the host application crash, shutdown suddenly.
In my repository, I catch the UpdateException, then, I create a custom exception, UniqueKeyException, that is throw to the caller. The caller is an auxiliar method that is called in the Begin method.
This auxiliar method, catch the UniqyeKeyException and only do a "throw", that is capture in the try/catch block of my end method. Here there is something that I don't understand, why in the end mehod this exception is catched in the block of AgregateException instead of the UniqueKeyException.
Well, anyway, in the catch block of the end method, in the AgregateException block, I check if the innerException is UniqueKeyException, if it is true, I create an object UniqueKeyArgs (a custom class with the information to send to the client), create a FaultException and finally do the throw FaultException. It is in this step, the throw, where the host application crash.
I think that I have all configure correctly, because my custom class UniqueKeyArgs is decorate as Datacontract and its properties as DataMember, in the app.config of my host application I configure the behavior to include exception details and in the contract I decorate it with faultContract.
Why the application crash?
My code is the following:
REPOSITORY
public List<Usuers> updateUsers(List<Users> paramUsers)
{
....
catch(UpdateException ex)
{
SqlException innerEx = (SqlException)ex.InnerException;
//Code 2627 is Unique Key exception from SQL Server.
if (innerEx != null && innerEx.Number == 2627)
{
//I create the conditions of searching
ConditionsUsers conditions = new conditions();
conditions.UserName = (Users)ex.StateEntries[0].Entity).userName;
//Search for the existing user
Users myUser = getUser(conditions);
string message = "the user " + conditions.userName + " exists.";
throw new UniqueKeyException(message, myUser);
}
throw;
}
SERVICE IMPLEMENTATION
//This is my auxiliar method, called in the Begin method.
private submitUpdates()
{
....
catch(UniqueKeyException ex)
{
//The code enter here
throw;
}
}
public IAsyncResult BeginUpdateUsers(List<users> paramUsers, AsyncCallback callback, object state)
{
Task<List<Users>> myTask= Task<List<Users>>.Factory.StartNew(p => sumbmitUpdates(paramUsers), state);
return myTask.ContinueWith(res => callback(myTask));
}
public List<Users> EndUpdateusers(IAsyncResult result)
{
try
{
return ((Task<List<Users>>)result).Result;
}
//Why agregateException and not is catched in the UniqueKeyException ???
catch(AgregateException ex)
{
if (innerExceptions[0] is UsuariosValorUnicoException)
{
//I assign manually the data to debug, to discard other problems.
Users myUser = new Users();
myUser.UserName = "Jhon";
myUser.Password = "pass123";
UniqueKeyArgs myArgs = new UniqueUserArgs("unique key error", myUser);
FaultException<UniqueKeyArgs> myException = new FaultException<UniqueKeyArgs>(myArgs);
//Crash here, in the throw myException
throw myException;
}
}
throw;
}
MY CONTRACT
[FaultContract(typeof(UniqueKeyArgs))]
IAsyncResult BeginUpdateUsers(List<Users> paramUser, AsyncCallback callback, object state);
List<Users> EndUpdateUsers(IAsyncResult result);
Crash when I throw myException in the End method.
I see in this post that the solution is catch the exception in the host application too, not only in the service object. However, this solution uses Application.ThreadException, that belong to System.Windows.Forms namespace, and I am using a WPF application.
How could I send the exception to the client from a service hosted in a WPF application?
Thanks.
EDIT1: well, I am use a try/catch block in the line where I throw the exception and I see that the error is that I have not indicated a reason, so when I create my FaultException I do:
FaultException<UniqueKeyArgs> myException = new FaultException<UniqueKeyArgs>(myArgs, new FaultReason("DummyReason");
In this case, the exception message is "DummyReason", the message that I set in the FaultReason, so it says me nothing. The FaultException is not throw, and throw the generic exception to the client.
In this case the host application does not shutdown, but close the connection with the client and I have to reconnect.
It seems that the problem is the creaton of the FaultException, but I don't see the problem.
#Roeal suggests that perhaps is only possible to use faultException with synch methods, but in this link I can see an example in which is used with async methods. I have seen others examples, is not the unique.
Thanks.
EDIT2: I solve my problem. My problem is that in the FaultException, T is an object that have a property that was a self tracking entity, and this is a problem, if I am not wrong, I only can use basic types as properties of the exception.
Then, in the exception, I have implmemented ISerialize. It's needed to be able to send the information to the client, without this, the client receives an exception.Detail with null properties.
Did you also declare the synchronous operation in your service contract? In that case, maybe this helps:
If fault contracts are defined on the service operation contract, the FaultContract attribute should be applied only on the synchronous operations.
-- Juval Lowy, "Programming WCF Services 3rd Edition" (p456)
I solve my problem. My problem is that in the FaultException, T is an object that have a property that was a self tracking entity, and this is a problem, if I am not wrong, I only can use basic types as properties of the exception.
Then, in the exception, I have implmemented ISerialize. It's needed to be able to send the information to the client, without this, the client receives an exception.Detail with null properties.

NHibernate with custom sql-insert vs catching procedure raised exceptions and out params

I have mapped classes with custom sql (insert, delete, update) through procedure calls. But, I noticed that when my insert procedure fails raising exception, the GenericAdoException from NHibernate doesn't have my message raised from the procedure.
But, all raised exceptions from procedures for delete and update is catched well, only the insert procedure hasn't its exception message catched.
Is that a limitation or a bug of NHibernate 3.2.4 when we use "native" generator for ids combined with custom sql ?
I'm searching also ways to get some out parameters from that procedures like a timestamp to each event (insert, delete and update), the timestamp is generated inside procedures.
EDIT: OUT PARAMs - I found the "generated" option over properties mapping options which we can ask to NHibernate to get params from procedures. This means that these properties have genarated values. So I tried to use generated="always" and works for insert, update and delete operations. Example: <property name="MyProp" generated="always"/>
I found that sql server driver doesn't put the messages raised by stored procedures into the SqlException when you run these stored procedures with ExecuteReader(). On the other hand NHibernate executes the custom sql-insert with ExecuteReader() (I debbuged its source code) and I guess it's right and necessary to get the key when it's mapped with native (or identity), my case.
Well, and now what to do ? I found also (hard to found) that the SqlConnection has a event called "InfoMessage" in which you can receive (catch) all messages sent from your stored procedures (raiserror). Now this is possible to "catch" these messages, but how to make them cross NHibernate core and be received by our application when we insert something session.save() ?
Altough we have access to session and so to the connection (SqlConnection) the messages was already lost, because them are only received by the delegate assigned to the event SqlConnection.InfoMessage before of its occurrence.
To solve this, I tried two approaches:
In the first I projected a way to register the delegate inside DriverConnectionProvider.GetConnection() and this delegate would store the messages on the thread context associating it with the connection, so these messages could be getted later.
In the second and the one choosed, I implemented IDbConnection and IDbCommand wrapping inside them the SqlConnection and SqlCommand (but I think the NHibernate has a bug because in some places it references DbConnection instead IDbConnection - like in ManagedProviderConnectionHelper, so I had to extend from DbConnection and DbCommand instead).
Inside my CustomSqlConnection I register the delegate and store the messages for later use.
This is working ! Work as standalone driver (ADO) either as a NHibernate driver.
The idea is:
public class CustomSqlConnection : DbConnection, IDbConnection {
private SqlConnection con;
private StringBuilder str = new StringBuilder(0);
public CustomSqlConnection() {
con = new SqlConnection();
con.InfoMessage += OnInfoMessage;
}
private void OnInfoMessage(object sender, SqlInfoMessageEventArgs e) {
if (str.Length > 0) {
str.Append("\n");
}
str.Append(e.Message);
}
public string FetchMessage() {
string msg = Message;
str.Clear();
return msg;
}
...
...
}
EDIT: The hard step is to implement all operations from DdConnection and Dbcommand, repassing the call to the sql instance (look the field con above), so:
...
public override void Open() {
con.Open();
}
...

Resources