There is now a way to throw an exception in ExpressX code that can be caught in the edmiNET binding's Execute function of the query object from the xpx machine. .
Works on externally callable the query functions in ExpressX that has generic return type (generic or aggregate of generic).
To raise an .NET xpxException in edmiNET you need to create a view_entity like this View_Entity Exception (as shown below) and return it in an aggregateAggregate Of Exception.
We use Aggregate of Exception to allow for more than one exception as a chain of inner exceptions:
Code Block | ||||
---|---|---|---|---|
| ||||
--------------------------------------------------------------------------------------------- -- Exception handling -- In the global section declare the following: -- GLOBAL -- GExceptions : Aggregate Of Exception := []; -- GException : Exception; -- ... -- END_GLOBAL; VIEW_ENTITY Exception; _Type_ : STRING; -- Either 'edmException' or 'xpxException' errCode : INTEGER; -- EDM error code as returned from xpxExceptionId errMessage : STRING; -- EDM error message as returned from xpxExceptionId userCode : INTEGER; -- Selfmade code userMessage : STRING; -- Selfmade message functionName : STRING; -- Function as returned from xpxExceptionId or selfmade lineNumber : INTEGER; -- Line number as returned from xpxExceptionId or selfmade. innerException : Exception; END_VIEW_ENTITY; |
The individual exception data is available in the xpxException object.
...
title | Express Helper functions and procedures |
---|---|
linenumbers | true |
collapse | true |
...
In the ExpressX code we recommend the following two exception handling utility functions:
- Function GetException(Message : String) : Aggregate Of Exception
- Procedure CancelException
Function GetException(Message : String) : Aggregate Of Exception;
Local
lInnerException : Exception;
lMessage : String;
lKeep : Boolean := True;
End_Local;
If NVL(xpxExceptionId.errCode,
...
0)
...
<>
...
0
...
Then
--
...
EDM error
-- Avoid reporting the same error twice
Repeat I := 1 To xpfSizeOf(GExceptions);
If (GExceptions[I].errCode = xpxExceptionId.errCode) And
(GExceptions[I].lineNumber = xpxExceptionId.lineNumber) Then
lKeep := False;
Escape;
End_If;
End_Repeat;
If lKeep Then
lInnerException := GException;
New GException;
GException._Type_ := 'edmException';
GException.errCode := xpxExceptionId.errCode;
GException.errMessage := xpfGetErrorText(xpxExceptionId.errCode);
...
GException.functionName :=
...
xpxExceptionId.functionName;
...
GException.lineNumber :=
...
xpxExceptionId.lineNumber;
...
GException.innerException
...
:=
...
lInnerException;
...
lMessage := xpfStringPrintf('Line
...
#%d:
...
Exception.
...
EDM
...
Error
...
number:
...
%d,
...
Message:
...
%s', NVL(xpxExceptionId.lineNumber,
...
xpxCurrentLine),
...
GException.errCode,
...
GException.errMessage
...
);
xpxPrintf('%s\n', lMessage); xpxDebugPrintf('%s\n', lMessage);
GExceptions ++ GException;
End_If;
End_If;
If NVL(Message,
...
'')
...
<>
...
''
...
Then
lInnerException :=
...
GException;
...
New GException;
GException._Type_
...
:=
...
'xpxException';
...
GException.userMessage :=
...
Message;
...
GException.innerException
...
:=
...
lInnerException;
...
lMessage := xpfStringPrintf('Line
...
#%d:
...
Exception:
...
Message:
...
%s', NVL(xpxExceptionId.lineNumber,
...
xpxCurrentLine),
...
GException.userMessage
...
);
xpxPrintf('%s\n', lMessage); xpxDebugPrintf('%s\n', lMessage);
GExceptions ++ GException;
End_If;
Return(GExceptions);
...
End_Function;
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
-- To ignore an exception from lower level and continue -- execution as normal call the following function. Procedure CancelException; GExceptions := []; GException := ?; End_Procedure; --------------------------------------------------------------------------------------------- |
Declare the follwing On_Error_Do block in the beginning of every function to ensure that all EDM errors are caught and that exceptions propagate upwards in the stack.
On_Error_Do xpxThrow(GetException(?)); End_On_Error_Do;
Throw "soft" errors from code like this:
xpxThrow(GetException('Something when wrong'));
To ignore an exception and reset exception chain:
On_Error_Do cancelException; End_On_Error_Do;
Catch the XPXException in edmiNET like this:
edmiNet VB:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
Try EnterpriseModel.NewQuery.Execute("CatDictionaryServices", "UpdateExchangeRequirementConceptAttribute", New Object() {New Instance(ProductPage.ERConceptId), New Instance(lGroupId), New Instance(lConceptId), Column.Name, NewValue}) RefreshRow = True Catch XPXEx As XPXException XtraMessageBox.Show(XPXEx.Message) Catch Ex As Exception XtraMessageBox.Show(Ex.ToString) End Try |
edmiNet C#:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
try { EnterpriseModel.NewQuery.Execute("CatDictionaryServices", "UpdateExchangeRequirementConceptAttribute", new object[] { new Instance(ProductPage.ERConceptId), new Instance(lGroupId), new Instance(lConceptId), Column.Name, NewValue }); RefreshRow = true; } catch (XPXException XPXEx) { XtraMessageBox.Show(XPXEx.Message); } catch (Exception Ex) { XtraMessageBox.Show(Ex.ToString); } |
...
Code Block | ||
---|---|---|
| ||
Error number 11298: Illegal data type or data value of argument #1. Function: xpfGetInstanceModel Line number: 1581 Query function: CatDictionaryServices.UpdateExchangeRequirementConceptAttribute |
...