Examine the scope with weak and strong references
- Last Updated: January 16, 2024
- 3 minute read
- OpenEdge
- Version 12.8
- Documentation
One final question before you move on: The Bin record buffer is scoped to the
two blocks inside the main DO block, but at what level is the
Warehouse record buffer scoped? Look back through the entire
procedure to come up with an answer before looking at this excerpt from the listing
file:
|
You see the two blocks where the Bin buffer is scoped. You also see that
the Warehouse buffer is scoped to the entire procedure (line 0). Why is
this?
There are several free references to the Warehouse buffer that are not
in blocks that provide record scoping. This includes, among others, the final
DO block of the procedure. As a result, the AVM raises the scope of
the buffer all the way to the procedure itself because there is no other block to scope
it to. In your sample procedure, which is only reading records from the database and not
updating them, it does not make a lot of difference. If the procedure had a transaction
that updated the Warehouse record, though, you might find that the
record and the record lock on it are held much longer than you expected or wanted,
resulting in record contention between different users accessing the table at the same
time.
What could you do to avoid this? Define a strong scope for the Warehouse
record wherever it is used.
To define a strong scope for the Warehouse record:
- First make the first
DOblock around theFIND Warehousestatement scope the buffer to the block:DO FOR Warehouse: FIND Warehouse WHERE Warehouse.WarehouseNum = Bin.WarehouseNum. - Press SHIFT+F2 to do a syntax check. This is what you
get:
Why did this error happen? You tried to force the scope of the buffer to this block, but the free reference in the
DOblock at the end of the procedure still forces the scope up to the top, and those two conflict. - Change the final
DOblock to place a strong scope there:DO FOR Warehouse: FIND Warehouse WHERE Warehouse.WarehouseNum = iEntry. - Now a syntax check succeeds. If you compile the procedure and get a listing file,
you see that the
Warehousebuffer is scoped all over the place:File Name Line Blk. Type Tran Blk. Label -------------------- ---- ----------- ---- -------------------------------- .\h-BinCheck.p 0 Procedure No .\h-BinCheck.p 14 For No Buffers: Sports2020.Warehouse .\h-BinCheck.p 19 Do No .\h-BinCheck.p 21 For No Buffers: Sports2020.Bin .\h-BinCheck.p 23 Do No Buffers: Sports2020.Warehouse .\h-BinCheck.p 31 Repeat No Buffers: Sports2020.Warehouse Sports2020.Bin .\h-BinCheck.p 36 Do No .\h-BinCheck.p 49 Do No .\h-BinCheck.p 51 Do No Buffers: Sports2020.Warehouse
Take a look at the scope for each of these blocks:
- The
Warehousebuffer is now scoped to the very firstFOR EACH Warehouseblock, with its weak scope. the AVM tried to do this before. Because the other references toWarehouseforced the scope up to the procedure level, this weak scope disappeared (that is why it is called weak). - It is scoped to the
DO FOR Warehouseblock because you added that strong-scoped reference. - It is also scoped to the
REPEAT PRESELECTblock. This is another weak scope that did not hold when the buffer scope was forced to the top. - It is scoped to the final
DO FOR Warehouseblock, with its strong-scoped reference you just added.
When you start writing serious procedures that update the database, you will be a lot more successful if you keep your buffer scope small like this. You should get into the habit now.