Strange behavior with try-catch on Dynamics Ax 2012 - try-catch

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.

Related

'NpgsqlBinaryImporter' does not contain a definition for 'Cancel'

As I write this, the documentation at https://www.npgsql.org/doc/copy.html#cancel says:
Import operations can be cancelled at any time by calling the Cancel()
method on the importer object. No data is committed to the database
before the importer is closed or disposed.
Export operations can be cancelled as well, also by calling Cancel().
I just updated my Npgsql package from 3.1.10 to 4.0.7, and now I get the error 'NpgsqlBinaryImporter' does not contain a definition for 'Cancel' for code similar to the following:
void WriteStuff(IEnumerable<RowInfo> enumerable, NpgsqlConnection conn)
{
using (var writer = conn.BeginBinaryImport("COPY blah blah FROM STDIN (FORMAT BINARY)"))
{
try
{
foreach (var rowInfo in enumerable)
{
writer.StartRow();
writer.Write(...); // blah blah
}
writer.Close();
}
catch
{
writer.Cancel();
throw;
}
}
}
It looks like this commit made Cancel() private.
So what is the correct way to cancel a bulk operation now? Do I need to wrap it in a transaction?
[And given the answer, I should just get rid of the try-catch code in the above code and just let the exception happen. Also the call to writer.Close() should change to writer.Complete(). ]
Npgsql 4.0 changed the COPY API around cancellation in a significant way, see the release notes.
In a nutshell, you must now explicitly call Complete() on NpgsqlBinaryImporter in order to commit the import; disposing it without calling Complete() will cancel the operation. This was done in order to make sure that exceptions don't cause a commit, and is aligned with how .NET TransactionScope work.
I'll update the documentation on this - thanks for pointing it out!

Entity Framework does not catch SQL Exception

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

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 Which messages to return after catching an exception?

I am using a wcf service and I know how to catch all the exceptions I need...
But I dont know which messages should I return?
My code:
try
{
currentPosition = await locator.GetGeopositionAsync();
}
catch (FaultException<MessageError> ex)
{
MessageBox.Show(...?);
}
catch (EndpointNotFoundException ex)
{
MessageBox.Show(...?);
}
catch (CommunicationException ex)
{
...
}
catch (Exception ex)
{
...
}
I can return ex.Message but I dont want the client to know all the details, I want to show a short and helpful message.
What should I do?
I have always handled this situation in a similar way to the way that #Tim suggested in his comment. I need as much information to be saved so that I can debug the problem at a later date, but as you said, we don't want to show the end user the developer Exception messages.
Therefore the solution that I use is simply to store the information that comes from the Exception in the database and to provide the user with 'user-friendly' error messages. Make sure that you also add code to record any inner Exceptions as well if they exist. Now to address the question as to what to put in these messages... it really depends on your situation, but I generally follow this procedure.
First, I work out (either from forward thinking or from test results) which are the most likely errors to occur... off the top of my head, I'm talking about errors like 'no network access', or 'invalid user security', etc.
When I have a number of possible errors, I will attempt to catch the exact errors with a number of catch statements as you have. Inside the handlers, I check for certain Exception messages and return pre-written user friendly messages for each. Finally, I add one last generic message to display for all unforeseen error situations.

Try Catch block in Siebel

I have a script which sends a set of records into a file. I'm using Try - Catch block to handle the exceptions. In the catch block I have a code where it has the pointer to next record. But this is not executing . Basically I wan to skip the bad record n move to next record.
while(currentrecord)
{
try
{
writerecord event
}
catch
{
currentrecord = next record
}
}
In most languages (unless you're using something very strange), If 'writerecord event' doesn't throw an exception, the catch block will not be called.
Don't you mean :
while(currentrecord) {
try { writerecord event }
catch { log error }
finally { currentrecord = next record}
}
Are you trying to loop through some records that are returned by a query? Do something like this:
var yourBusObject = TheApplication().GetBusObject("Your Business Object Name");
var yourBusComp = yourBusObject.GetBusComp("Your Business Component Name");
// activate fields that you need to access or update here
yourBusComp.ClearToQuery();
// set search specs here
yourBusComp.ExecuteQuery(ForwardOnly);
if (yourBusComp.FirstRecord()) {
do {
try {
// update the fields here
yourBusComp.WriteRecord();
} catch (e) {
// undo any changes so we can go to the next record
// If you don't do this I believe NextRecord() will implicitly save and trigger the exception again.
yourBusComp.UndoRecord();
// maybe log the error here, or just ignore it
}
} while (yourBusComp.NextRecord());
}
You can use try-finally structure so that whatever inside the finally block will always be executed, regardless of whether the code throws an exception or not. It's often used to clean up resources such as closing files or connections. Without a catch clause, any thrown exception in your try block will abort execution, jump to your finally block and run that code.
Agree that 'finally' might be the best bet here - but do we know what the exception actually is ? - can you output it in your catch loop, so that :
A) you can prove an exception is being thrown (rather than say a 'null' being returned or something)
B) Make sure the exception you get isn't something that could prevent 'nextrecord' working as well...[not sure what the 'finally' would achieve in the case - presumably the exception would have to bubble up to calling code?
So you're trying to move onto the next record if you failed to commit this one. Robert Muller had it right. To explain...
If the WriteRecord fails, then the business component will still be positioned on the dirty record. Attempting to move to the next record will make the buscomp try to write it again--because of a feature called "implicit saving".
Solution: You'll have to undo the record (UndoRecord) to abandon your failing field changes before moving onto the next one.

Resources