D
dbeavon
Guest
I don't think my question is clear so I will give a more detailed repro. Lets say I have a business logic class "BomLogic" and a testing harness that interacts with it "TestClient". If BomLogic independently BIND's its own reference to a dataset into the reference-only member, then that dataset will be available to use indefinitely . But if TestClient sends in the instance of the data as a parameter, then the dataset will be pulled away and won't be available for use when BomLogic does subsequent work. Here is BomLogic. Note that InitDataMethod1 will bind the dataset reference independently. But TestMethod1 will allow the dataset reference to be provided as a parameter: USING Progress.Lang.*. BLOCK-LEVEL ON ERROR UNDO, THROW. CLASS app.Production.Maintenance.Bom.Assembly.Testing.BomLogic: {app/Production/Maintenance/Bom/Assembly/AsmBomData.i REFERENCE-ONLY} /* ********************************************************************* */ /* Init the reference only data from BIND */ /* ********************************************************************* */ METHOD PUBLIC VOID InitDataMethod1(): DEFINE VARIABLE v_Init AS app.Production.Maintenance.Bom.Assembly.ReadOnlyHelpers.DataUtil.DataInitializerForBom NO-UNDO. v_Init = app.Production.Maintenance.Bom.Assembly.ReadOnlyHelpers.DataUtil.DataInitializerForBom:NewInitializerInstance(). v_Init:BindNewBomData(OUTPUT DATASET DS_AsmBom BIND). CREATE TT_BomHeader. TT_BomHeader.BomCode = "A". TT_BomHeader.OurRecId = "B". END METHOD. /* ********************************************************************* */ /* Init the reference only data from input */ /* ********************************************************************* */ METHOD PUBLIC VOID TestMethod1(INPUT DATASET DS_AsmBom): FOR EACH TT_BomHeader NO-LOCK: DISPLAY TT_BomHeader.BomCode. END. END METHOD. /* ********************************************************************* */ /* Secondary method after data is available */ /* ********************************************************************* */ METHOD PUBLIC VOID TestMethod2(): MESSAGE "HERE {&FILE-NAME} {&LINE-NUMBER} IN TEST METHOD 2". PAUSE. FOR EACH TT_BomHeader NO-LOCK: DISPLAY TT_BomHeader.BomCode. END. MESSAGE "HERE {&FILE-NAME} {&LINE-NUMBER} DONE!". PAUSE. END METHOD. END CLASS. Given that BomLogic class, here is the test harness that uses it: USING Progress.Lang.*. USING app.Production.Maintenance.Bom.Assembly.Testing.*. BLOCK-LEVEL ON ERROR UNDO, THROW. CLASS app.Production.Maintenance.Bom.Assembly.Testing.TestClient: /* References datasets */ {app/Production/Maintenance/Bom/Assembly/AsmBomData.i REFERENCE-ONLY} /* ********************************************************************* */ /* Creates dataset and sends it to BomLogic class, TestMethod2 fails. */ /* ********************************************************************* */ METHOD PUBLIC VOID ClientTestMethod1(): DEFINE VARIABLE v_Init AS app.Production.Maintenance.Bom.Assembly.ReadOnlyHelpers.DataUtil.DataInitializerForBom NO-UNDO. v_Init = app.Production.Maintenance.Bom.Assembly.ReadOnlyHelpers.DataUtil.DataInitializerForBom:NewInitializerInstance(). v_Init:BindNewBomData(OUTPUT DATASET DS_AsmBom BIND). CREATE TT_BomHeader. TT_BomHeader.BomCode = "A". TT_BomHeader.OurRecId = "B". FOR EACH TT_BomHeader NO-LOCK: DISPLAY TT_BomHeader.BomCode. END. DEFINE VARIABLE v_RefObj AS BomLogic NO-UNDO. v_RefObj = NEW BomLogic(). v_RefObj:TestMethod1(INPUT DATASET DS_AsmBom BY-REFERENCE ). v_RefObj:TestMethod2(). END METHOD. /* ********************************************************************* */ /* Allows BomLogic to create its own data, TestMethod2 succeeds */ /* ********************************************************************* */ METHOD PUBLIC VOID ClientTestMethod2(): DEFINE VARIABLE v_RefObj AS BomLogic NO-UNDO. v_RefObj = NEW BomLogic(). v_RefObj:InitDataMethod1(). v_RefObj:TestMethod2(). END METHOD. END CLASS. Finally for reference purposes, here is a simple utility class where the dataset is actually instantiated. All this does is provide a way to create the instance of the dataset. That instance can be used by any other class which only has a "BY-REFERENCE" member. USING Progress.Lang.*. USING app.Production.Maintenance.Bom.Assembly.ReadOnlyHelpers.DataUtil.*. BLOCK-LEVEL ON ERROR UNDO, THROW. CLASS app.Production.Maintenance.Bom.Assembly.ReadOnlyHelpers.DataUtil.DataInitializerForBom : /* Data has actual instance. NOT only a reference */ {app/Production/Maintenance/Bom/Assembly/AsmBomData.i} CONSTRUCTOR PUBLIC DataInitializerForBom ( ): SUPER (). END CONSTRUCTOR. METHOD PUBLIC STATIC DataInitializerForBom NewInitializerInstance(): RETURN NEW DataInitializerForBom(). END METHOD. METHOD PUBLIC VOID BindNewBomData(OUTPUT DATASET FOR DS_AsmBom BIND) : DATASET DS_AsmBom:EMPTY-DATASET (). END METHOD. END CLASS. So given the BomLogic and the TestClient, why does running the TestClient:ClientTestMethod1 () fail with "attempt to reference uninitialized temp-table"? But TestClient:ClientTestMethod2 () will succeed and will not pull away the reference to the dataset that the BomLogic relies on. This is behavior that is unpredictable and hard to understand. I thought I knew how to work with REFERENCE-ONLY datasets. I thought they worked like memory references (pointers to an instance of a DATASET that had been instantiated elsewhere). What I didn't expect is that the memory reference would be taken away from me after it had been previously available for use. Any help would be appreciated. I'd really like a "sticky" reference that wouldn't be removed once it had been assigned (even if the reference comes in as an input parameter).
Continue reading...
Continue reading...