SQL server 2005 / SQL server 2008 behaviour versus C/AL Code

Remco
Member Posts: 81
Situation:
We have taken over a customer of another Solution Center.
A codeunit was written to run some jobs from the job scheduler executed by a NAS.
This codeunit contains a loop where fields are updated which are in the current key (The famous Next from Hell). As the example below:
recCust.SETRANGE("Country/Region Code", 'BE');
IF recCust.FINDSET(TRUE) THEN
REPEAT
recCust.VALIDATE("Country/Region Code", 'US');
recCust.MODIFY;
UNTIL recCust.NEXT = 0;
I'm convinced that this code causes problems to execute all the jobs of the job scheduler.
This code is already a few years old. In the past they didn't have that much problems with this piece of code.
Since they have upgraded the SQL server from 2005 to 2008 the problems became more frequent.
My question is if this SQL server 2008 reacts different to this "Next from Hell" than SQL server 2005?
The customer is using a 3.70 database with a 5.0 SP1 client.
We have taken over a customer of another Solution Center.
A codeunit was written to run some jobs from the job scheduler executed by a NAS.
This codeunit contains a loop where fields are updated which are in the current key (The famous Next from Hell). As the example below:
recCust.SETRANGE("Country/Region Code", 'BE');
IF recCust.FINDSET(TRUE) THEN
REPEAT
recCust.VALIDATE("Country/Region Code", 'US');
recCust.MODIFY;
UNTIL recCust.NEXT = 0;
I'm convinced that this code causes problems to execute all the jobs of the job scheduler.
This code is already a few years old. In the past they didn't have that much problems with this piece of code.
Since they have upgraded the SQL server from 2005 to 2008 the problems became more frequent.
My question is if this SQL server 2008 reacts different to this "Next from Hell" than SQL server 2005?
The customer is using a 3.70 database with a 5.0 SP1 client.
0
Comments
-
i generally use marked records and remove the filter after marking them just to stop from having to go through the loop all the time
or replace it with a modifyall in this case
as far as i can tell from experience i havent seen much of a difference in behaviour between the 2 sql versions when working with a database for this kind of loops.0 -
The SQL Server for sure does not react differently, because it has not the faintest clue about the C/AL code.
What matters is how NAV queries the data, and this is a matter of the NAV Client Version - did you accomplish a "Technical Upgrade" with NAV while upgrading the SQL Server?
But as you said, tgis code sucks; better do the changes on a separate variable:recCust.SETRANGE("Country/Region Code", 'BE'); IF recCust.FINDSET THEN REPEAT recCust2.GET(recCust."No."); recCust2.VALIDATE("Country/Region Code", 'US'); recCust2.MODIFY; UNTIL recCust.NEXT = 0;
Jörg A. Stryk (MVP - Dynamics NAV)
NAV/SQL Performance Optimization & Troubleshooting
STRYK System Improvement
The Blog - The Book - The Tool0 -
I'd say a MODIFYALL would be even better.
recCust.SETRANGE("Country/Region Code", 'BE'); IF NOT recCust.ISEMPTY THEN recCust2.MODIFYALL("Country/Region Code", 'US');
And maybe add a SETCURRENTKEY with "Country/Region Code" in it?0 -
Shedman wrote:I'd say a MODIFYALL would be even better.
recCust.SETRANGE("Country/Region Code", 'BE'); IF NOT recCust.ISEMPTY THEN recCust2.MODIFYALL("Country/Region Code", 'US');
0 -
This issue was not about this code. It was just an example that I copied to explain the case.
It is actually about the standard NAV 3.70 code to start the job scheduler.JobSchedSetup.RESET; JobSchedSetup.SETCURRENTKEY("Next Check Date","Next Check Time"); IF RunStatus <> JobSchedSetup."Run Status"::"Special Order" THEN JobSchedSetup.SETFILTER("Next Check Date",'<>%1',0D); JobSchedSetup.SETRANGE("Run Status",RunStatus); JobSchedSetup.SETRANGE(Enabled,TRUE); IF JobSchedSetup.FIND('-') THEN BEGIN REPEAT IF RunNow(JobSchedSetup."Next Check Date",JobSchedSetup."Next Check Time") OR (JobSchedSetup."Run Status" = JobSchedSetup."Run Status"::"Special Order") THEN BEGIN JobIdBeingProcessed := JobSchedSetup.ID; IF RunObjectFromJobSched.RUN(JobSchedSetup) THEN BEGIN JobIdBeingProcessed := ''; LastJobIdProcessed := JobSchedSetup.ID; LastMessage := JobSchedSetup."Message Text"; JobSchedSetup.GET(JobSchedSetup.ID); IF JobSchedSetup."Error Occurred" THEN BEGIN ErrorHandling(JobSchedSetup); UpdateStatus(JobSchedSetup.ID,JobSchedSetup."Message Text",TRUE,TRUE); END ELSE BEGIN NewDateAndTime(JobSchedSetup); UpdateStatus(JobSchedSetup.ID,JobSchedSetup."Message Text",FALSE,TRUE); END; COMMIT; END ELSE BEGIN ErrorHandling(JobSchedSetup); UpdateStatus(JobSchedSetup.ID,JobSchedSetup."Message Text",TRUE,TRUE); JobIdBeingProcessed := ''; LastJobIdProcessed := JobSchedSetup.ID; LastMessage := JobSchedSetup."Message Text"; COMMIT; END; END; UNTIL JobSchedSetup.NEXT = 0; END;
If there was an error in the proces the Runstatus is changed in codeunit RunObjectFromJobSched
Then Navision losses his pointer and the Job Scheduler can skip some jobs.
Microsoft already changed the code in NAV 4.0 by using 2 variables. JobSchedSetup & JobSchedSetup2JobSchedSetup2.RESET; JobSchedSetup2.SETCURRENTKEY("Next Check Date","Next Check Time"); JobSchedSetup2.SETFILTER("Next Check Date",'<>%1',0D); JobSchedSetup2.SETRANGE( "Run Status", JobSchedSetup2."Run Status"::" ", JobSchedSetup2."Run Status"::"With Error"); JobSchedSetup2.SETRANGE(Enabled,TRUE); IF JobSchedSetup2.FIND('-') THEN BEGIN REPEAT JobSchedSetup := JobSchedSetup2; IF RunNow( JobSchedSetup."Next Check Date", JobSchedSetup."Next Check Time") THEN BEGIN IF AllObj.GET(JobSchedSetup."Object Type",JobSchedSetup."Object No.") THEN BEGIN IF RunObjectFromJobSched.RUN(JobSchedSetup) THEN BEGIN JobSchedSetup.LOCKTABLE; NewDateAndTime(JobSchedSetup); END ELSE BEGIN JobSchedSetup.LOCKTABLE; JobSchedSetup."Message Text" := ''; ErrorHandling(JobSchedSetup); END; END ELSE BEGIN JobSchedSetup.LOCKTABLE; JobSchedSetup."Message Text" := STRSUBSTNO(Text020,JobSchedSetup."Object Type",JobSchedSetup."Object No."); ErrorHandling(JobSchedSetup); END; JobSchedSetup.MODIFY; UpdateStatus(JobSchedSetup.ID,JobSchedSetup."Message Text",FALSE); JobSchedMgtSetup.GET; JobSchedMgtSetup."Last Job ID Processed" := JobSchedSetup.ID; JobSchedMgtSetup."Last Message" := JobSchedSetup."Message Text"; JobSchedMgtSetup.MODIFY; COMMIT; END; UNTIL JobSchedSetup2.NEXT = 0; END;
I assume that this is to prevent the lost of the pointer.
As said earlier our customer runs on a 5.0 SP1 client (not since the migration).
Is it better to use 2 variables or to use FINDSET(TRUE,TRUE)0
Categories
- All Categories
- 73 General
- 73 Announcements
- 66.6K Microsoft Dynamics NAV
- 18.7K NAV Three Tier
- 38.4K NAV/Navision Classic Client
- 3.6K Navision Attain
- 2.4K Navision Financials
- 116 Navision DOS
- 851 Navision e-Commerce
- 1K NAV Tips & Tricks
- 772 NAV Dutch speaking only
- 617 NAV Courses, Exams & Certification
- 2K Microsoft Dynamics-Other
- 1.5K Dynamics AX
- 320 Dynamics CRM
- 111 Dynamics GP
- 10 Dynamics SL
- 1.5K Other
- 990 SQL General
- 383 SQL Performance
- 34 SQL Tips & Tricks
- 35 Design Patterns (General & Best Practices)
- 1 Architectural Patterns
- 10 Design Patterns
- 5 Implementation Patterns
- 53 3rd Party Products, Services & Events
- 1.6K General
- 1.1K General Chat
- 1.6K Website
- 83 Testing
- 1.2K Download section
- 23 How Tos section
- 252 Feedback
- 12 NAV TechDays 2013 Sessions
- 13 NAV TechDays 2012 Sessions