Problem description: Upper limit for open cursors has been exceeded
When you are working in Dynamics AX, you receive following error: Upper limit for open cursors has been exceeded (90) - use parameter openCursors or change the X++ code.
Solution: Change the X++ code
An easy solution is to increase the maximum limit of open cursors, which is by default 90. But this often means only a postponement of this error message, as it may come back in future.
In most case you should change the X++ code, especially if the error message is coming from custom development. But one of the problems is how to find the X++ code causing the exceeding of the limit of open cursors (and for sure if you didn't write the X++ code yourself...). To find this, I wrote a class which traces the number of open cursors. To use it, call the class on severeral places in your own X++ code: the class will log the number of open cursors together with the stack. As such, you will get an evolution of the number of open cursors during execution of your own X++ code, which can help you to find the erroneous X++ code.
The class has 3 methods:
method 1: classDeclaration
// Class to count unfreed cursors
// Call this class as in methods where you want to count
// the unfreed cursors at that moment: CountUnfreedCursors::construct().run();
// Make sure c:\windows\temp directory exists on the client running the class
class CountUnfreedCursors
{
}
method 2: run
void run()
{HeapCheck hc = new HeapCheck('dump.log');
int rowIndex;
Common unfreedCursor;
DictTable dict;
ASCIIIO file = new ASCIIIO("c:\\windows\\temp\\" + date2str(Today(),321,2,0,2,0,4) + "CountUnfreedCursors.log","a");
container filecon;
container stack;
;
file.outFieldDelimiter(";");
file.outRecordDelimiter("\r\n");
stack = xSession::xppCallStack();
hc.firstUnfreedCursor();
rowIndex = 0;
while (hc.moreUnfreedCursors())
{filecon = connull();
rowIndex++;
unfreedCursor = hc.getUnfreedCursor();
dict = new DictTable (unfreedCursor.TableId);
filecon = conins(filecon,conlen(filecon)+1,conpeek(stack,3));
filecon = conins(filecon,conlen(filecon)+1,conpeek(stack,4));
filecon = conins(filecon,conlen(filecon)+1,date2str(Today(),321,2,1,2,1,4) + " " + time2str(TimeNow(),1,1));
filecon = conins(filecon,conlen(filecon)+1,"Table: " + dict.name());
filecon = conins(filecon,conlen(filecon)+1,"Use count: " + int2str(unfreedCursor.usageCount()));
hc.nextUnfreedCursor();
file.write(filecon);
}
filecon = connull();
filecon = conins(filecon,conlen(filecon)+1,"Unfreed cursors: " + int2str(rowIndex));
file.write(filecon);
file.write("------------------------------------------------------------------------------\r\n");
}
method 3: construct
static CountUnfreedCursors construct()
{CountUnfreedCursors countUnfreedCursors = new CountUnfreedCursors();
;
return countUnfreedCursors;
}
Other interesting resources about the upper limit for open cursors in Dynamics AX:
Continue reading......